From 748b7afc934164fa5b0e2e3aaf9ead198a708901 Mon Sep 17 00:00:00 2001 From: Kate F Date: Thu, 30 May 2024 15:27:51 +0100 Subject: [PATCH] Add fsm_new_statealloc(), to pre-allocate to a known number of states. --- include/fsm/fsm.h | 9 +++++++++ src/libfsm/charset.c | 3 +-- src/libfsm/clone.c | 2 +- src/libfsm/fsm.c | 14 ++++++++++++-- src/libfsm/reverse.c | 2 +- src/libre/re_strings.c | 1 + 6 files changed, 25 insertions(+), 6 deletions(-) diff --git a/include/fsm/fsm.h b/include/fsm/fsm.h index 1904814bd..2fea117cd 100644 --- a/include/fsm/fsm.h +++ b/include/fsm/fsm.h @@ -60,6 +60,15 @@ struct fsm_end_ids { struct fsm * fsm_new(const struct fsm_options *opt); +/* + * As fsm_new(), but with an explicit number of pre-allocated states. + * This is intended to save on internal reallocations for situations + * where it's known in advance exactly how many states an FSM will have. + * You can still add more states per usual. + */ +struct fsm * +fsm_new_statealloc(const struct fsm_options *opt, size_t statealloc); + /* * Free a structure created by fsm_new(), and all of its contents. * No other pointers returned by this API are to be freed individually. diff --git a/src/libfsm/charset.c b/src/libfsm/charset.c index dd8a679ed..662c0ac1f 100644 --- a/src/libfsm/charset.c +++ b/src/libfsm/charset.c @@ -36,8 +36,7 @@ fsm_intersect_charset(struct fsm *a, size_t n, const char *charset) { fsm_state_t state; - // TODO: pass .statealloc explicitly, we know it's 1. the default is overkill - b = fsm_new(a->opt); + b = fsm_new_statealloc(a->opt, 1); if (b == NULL) { return NULL; } diff --git a/src/libfsm/clone.c b/src/libfsm/clone.c index bec16bb0f..78511b12c 100644 --- a/src/libfsm/clone.c +++ b/src/libfsm/clone.c @@ -35,7 +35,7 @@ fsm_clone(const struct fsm *fsm) assert(fsm != NULL); assert(fsm->opt != NULL); - new = fsm_new(fsm->opt); + new = fsm_new_statealloc(fsm->opt, fsm->statecount); if (new == NULL) { return NULL; } diff --git a/src/libfsm/fsm.c b/src/libfsm/fsm.c index d027825ff..0e46962d1 100644 --- a/src/libfsm/fsm.c +++ b/src/libfsm/fsm.c @@ -44,11 +44,15 @@ free_contents(struct fsm *fsm) } struct fsm * -fsm_new(const struct fsm_options *opt) +fsm_new_statealloc(const struct fsm_options *opt, size_t statealloc) { static const struct fsm_options defaults; struct fsm *new, f; + if (statealloc == 0) { + return fsm_new(opt); + } + if (opt == NULL) { opt = &defaults; } @@ -60,7 +64,7 @@ fsm_new(const struct fsm_options *opt) return NULL; } - new->statealloc = FSM_DEFAULT_STATEALLOC; + new->statealloc = statealloc; new->statecount = 0; new->endcount = 0; new->capture_info = NULL; @@ -92,6 +96,12 @@ fsm_new(const struct fsm_options *opt) return new; } +struct fsm * +fsm_new(const struct fsm_options *opt) +{ + return fsm_new_statealloc(opt, FSM_DEFAULT_STATEALLOC); +} + void fsm_free(struct fsm *fsm) { diff --git a/src/libfsm/reverse.c b/src/libfsm/reverse.c index e896a1bff..b802f364d 100644 --- a/src/libfsm/reverse.c +++ b/src/libfsm/reverse.c @@ -54,7 +54,7 @@ fsm_reverse(struct fsm *fsm) if (fsm->endcount == 0 || !fsm_getstart(fsm, &prevstart)) { struct fsm *new; - new = fsm_new(fsm->opt); + new = fsm_new_statealloc(fsm->opt, 1); if (new == NULL) { return 0; } diff --git a/src/libre/re_strings.c b/src/libre/re_strings.c index b2f04fec1..ff8b2b4ab 100644 --- a/src/libre/re_strings.c +++ b/src/libre/re_strings.c @@ -96,6 +96,7 @@ re_strings_build(struct re_strings *g, } } + /* TODO: count trie nodes and fsm_new_statealloc() */ fsm = fsm_new(opt); if (fsm == NULL) { goto error;