diff --git a/README.md b/README.md index b772da4..ed9ab54 100644 --- a/README.md +++ b/README.md @@ -13,13 +13,13 @@ this notice are preserved. This file is offered as-is, without any warranty. ctlseqs - helper library for terminal control sequences -# Description +## About The ctlseqs library provides C API for manipulating terminal emulators with control sequences. ctlseqs is free software. you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. -# Getting Started +## Getting Started To install and use the library, see [INSTALL.md](INSTALL.md) for details. diff --git a/src/ctlseqs.c b/src/ctlseqs.c index 1d3a09c..f980f00 100644 --- a/src/ctlseqs.c +++ b/src/ctlseqs.c @@ -59,9 +59,13 @@ # define CTLSEQS_HOT #endif // HAVE_FUNC_ATTRIBUTE_HOT -#ifndef CTLSEQS_TRIE_INIT_SIZE -# define CTLSEQS_TRIE_INIT_SIZE 16 -#endif // !CTLSEQS_TRIE_INIT_SIZE +#ifndef CTLSEQS_TRIE_NODE_POOL_INIT_SIZE +# define CTLSEQS_TRIE_NODE_POOL_INIT_SIZE 16 +#endif // !CTLSEQS_TRIE_NODE_POOL_INIT_SIZE + +#ifndef CTLSEQS_TRIE_NODE_POOL_MAX_NUM +# define CTLSEQS_TRIE_NODE_POOL_MAX_NUM 8 +#endif // !CTLSEQS_TRIE_NODE_POOL_MAX_NUM #define CTLSEQS_VALUE_STR(stop_cond) \ for (cnt = 0; ; ++cnt) { \ @@ -127,8 +131,9 @@ struct ctlseqs_match_ctx { struct ctlseqs_matcher { struct ctlseqs_trie_node root; - struct ctlseqs_trie_node *node_pool; - size_t node_pool_size; + struct ctlseqs_trie_node *node_pools[CTLSEQS_TRIE_NODE_POOL_MAX_NUM]; + size_t pool_idx; + size_t pool_size; struct ctlseqs_match_ctx *match_stack; }; @@ -384,24 +389,25 @@ ctlseqs_match(struct ctlseqs_reader *reader, struct ctlseqs_matcher const *match struct ctlseqs_matcher * ctlseqs_matcher_init() { + struct ctlseqs_trie_node *pool = malloc(sizeof(struct ctlseqs_trie_node) * CTLSEQS_TRIE_NODE_POOL_INIT_SIZE); struct ctlseqs_matcher *matcher = malloc(sizeof(struct ctlseqs_matcher)); - if (CTLSEQS_LIKELY(matcher != NULL)) { - *matcher = (struct ctlseqs_matcher) { .node_pool_size = 0 }; + if (CTLSEQS_UNLIKELY(pool == NULL || matcher == NULL)) { + free(pool); + free(matcher); + return NULL; } + *matcher = (struct ctlseqs_matcher) { + .node_pools = { pool }, + .pool_size = CTLSEQS_TRIE_NODE_POOL_INIT_SIZE + }; return matcher; } int ctlseqs_matcher_config(struct ctlseqs_matcher *matcher, struct ctlseqs_matcher_options const *options) { - size_t node_pool_idx = 0, max_format_size = 0; - if (matcher->node_pool == NULL) { - matcher->node_pool_size = sizeof(struct ctlseqs_trie_node) * CTLSEQS_TRIE_INIT_SIZE; - matcher->node_pool = malloc(matcher->node_pool_size); - if (CTLSEQS_UNLIKELY(matcher->node_pool == NULL)) { - return CTLSEQS_NOMEM; - } - } + size_t node_idx = 0, max_format_size = 0; + struct ctlseqs_trie_node *node_pool = matcher->node_pools[matcher->pool_idx]; matcher->root = (struct ctlseqs_trie_node) { .value = -1 }; for (size_t i = 0; i < options->npatterns; ++i) { char const *pattern = options->patterns[i]; @@ -421,15 +427,19 @@ ctlseqs_matcher_config(struct ctlseqs_matcher *matcher, struct ctlseqs_matcher_o if (node != NULL) { continue; } - if (CTLSEQS_UNLIKELY(++node_pool_idx >= matcher->node_pool_size)) { - struct ctlseqs_trie_node *new_pool = realloc(matcher->node_pool, matcher->node_pool_size * 2); - if (CTLSEQS_UNLIKELY(new_pool == NULL)) { + if (CTLSEQS_UNLIKELY(++node_idx >= matcher->pool_size)) { + if (CTLSEQS_UNLIKELY(++matcher->pool_idx >= CTLSEQS_TRIE_NODE_POOL_MAX_NUM)) { return CTLSEQS_NOMEM; } - matcher->node_pool = new_pool; - matcher->node_pool_size *= 2; + node_pool = malloc(sizeof(struct ctlseqs_trie_node) * matcher->pool_size * 2); + if (CTLSEQS_UNLIKELY(node_pool == NULL)) { + return CTLSEQS_NOMEM; + } + node_idx = 0; + matcher->node_pools[matcher->pool_idx] = node_pool; + matcher->pool_size *= 2; } - old_node->children[ch] = node = &matcher->node_pool[node_pool_idx]; + old_node->children[ch] = node = node_pool + node_idx; *node = (struct ctlseqs_trie_node) { .value = -1, // Value -1 indicates that there's no match on current node. .placeholder = ch < ctlseqs_ph_begin || ch >= ctlseqs_ph_end ? 0 : ch, @@ -458,7 +468,10 @@ CTLSEQS_COLD void ctlseqs_matcher_free(struct ctlseqs_matcher *matcher) { if (matcher != NULL) { - free(matcher->node_pool); + for (size_t idx = 0; idx <= matcher->pool_idx; ++idx) { + free(matcher->node_pools[idx]); + } + free(matcher->match_stack); free(matcher); } } diff --git a/tests/tcsgrep.c b/tests/tcsgrep.c index 52f8448..87c538e 100644 --- a/tests/tcsgrep.c +++ b/tests/tcsgrep.c @@ -440,6 +440,9 @@ main(int argc, char **argv) } terminate: + free(patterns); + ctlseqs_matcher_free(matcher); + ctlseqs_reader_free(reader); tcsetattr(STDIN_FILENO, TCSANOW, &old_termios); return status; }