diff options
author | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2023-06-09 16:10:30 +0900 |
---|---|---|
committer | Nobuyoshi Nakada <nobu@ruby-lang.org> | 2023-06-09 20:22:30 +0900 |
commit | ab6eb3786c94e69c561080cbb796c2381702a3a4 (patch) | |
tree | 2fe551edd62566939a7760439851fd7ad90b2d13 /regcomp.c | |
parent | d54f66d1b4ce32d78b526b1ea9e3f213a763d07c (diff) |
Optimize `Regexp#dup` and `Regexp.new(/RE/)`
When copying from another regexp, copy already built `regex_t` instead
of re-compiling its source.
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/7922
Diffstat (limited to 'regcomp.c')
-rw-r--r-- | regcomp.c | 74 |
1 files changed, 74 insertions, 0 deletions
@@ -5671,6 +5671,80 @@ onig_free(regex_t* reg) } } +static void* +dup_copy(const void *ptr, size_t size) +{ + void *newptr = xmalloc(size); + if (IS_NOT_NULL(newptr)) { + memcpy(newptr, ptr, size); + } + return newptr; +} + +extern int +onig_reg_copy(regex_t** nreg, regex_t* oreg) +{ + if (IS_NOT_NULL(oreg)) { + regex_t *reg = *nreg = (regex_t* )xmalloc(sizeof(regex_t)); + if (IS_NULL(reg)) return ONIGERR_MEMORY; + + *reg = *oreg; + +# define COPY_FAILED(mem, size) IS_NULL(reg->mem = dup_copy(reg->mem, size)) + + if (IS_NOT_NULL(reg->exact)) { + size_t exact_size = reg->exact_end - reg->exact; + if (COPY_FAILED(exact, exact_size)) + goto err; + (reg)->exact_end = (reg)->exact + exact_size; + } + + if (IS_NOT_NULL(reg->int_map)) { + if (COPY_FAILED(int_map, sizeof(int) * ONIG_CHAR_TABLE_SIZE)) + goto err_int_map; + } + if (IS_NOT_NULL(reg->int_map_backward)) { + if (COPY_FAILED(int_map_backward, sizeof(int) * ONIG_CHAR_TABLE_SIZE)) + goto err_int_map_backward; + } + if (IS_NOT_NULL(reg->p)) { + if (COPY_FAILED(p, reg->alloc)) + goto err_p; + } + if (IS_NOT_NULL(reg->repeat_range)) { + if (COPY_FAILED(repeat_range, reg->repeat_range_alloc * sizeof(OnigRepeatRange))) + goto err_repeat_range; + } + if (IS_NOT_NULL(reg->name_table)) { + if (IS_NULL(reg->name_table = st_copy(reg->name_table))) + goto err_name_table; + } + if (IS_NOT_NULL(reg->chain)) { + if (onig_reg_copy(®->chain, reg->chain)) + goto err_chain; + } + return 0; +# undef COPY_FAILED + + err_chain: + onig_st_free_table(reg->name_table); + err_name_table: + xfree(reg->repeat_range); + err_repeat_range: + xfree(reg->p); + err_p: + xfree(reg->int_map_backward); + err_int_map_backward: + xfree(reg->int_map); + err_int_map: + xfree(reg->exact); + err: + xfree(reg); + return ONIGERR_MEMORY; + } + return 0; +} + #ifdef RUBY size_t onig_memsize(const regex_t *reg) |