Mercurial > libjeffpc > bad-patches
view 2018-11-17-1-WIP__rope.patch @ 0:3e042207d646
first batch of patches
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Sat, 17 Nov 2018 12:02:16 -0500 |
parents | |
children |
line wrap: on
line source
# HG changeset patch # User Josef 'Jeff' Sipek <jeffpc@josefsipek.net> # Date 1492309700 14400 # Sat Apr 15 22:28:20 2017 -0400 # Node ID fe935c48619d33820fda3c20c3548be5516e3351 # Parent a25ff7b067d556fe3f0af72133f2bf2f87633a7e # EXP-Topic rope WIP: rope Sometimes a string is just not good enough. For some of those times, a rope will work much better. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net> diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,7 @@ add_library(jeffpc SHARED padding.c qstring.c rand.c + rope.c sexpr.c sexpr_dump.c sexpr_eval.c diff --git a/include/jeffpc/rope.h b/include/jeffpc/rope.h new file mode 100644 --- /dev/null +++ b/include/jeffpc/rope.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __JEFFPC_ROPE_H +#define __JEFFPC_ROPE_H + +#include <jeffpc/refcnt.h> +#include <jeffpc/str.h> +#include <jeffpc/list.h> + +/* scatter-gather string */ + +struct rope_node { + struct list_node node; + struct str *str; +}; + +struct rope { + struct list_node list; + size_t nodes; /* length of list */ + size_t len; /* length of string */ +}; + +extern struct rope *rope_alloc(void); +extern void rope_free(struct rope *rope); +extern int rope_append_rope(struct rope *a, struct rope *b); +extern int rope_append_str(struct rope *a, struct str *b); +extern int rope_append_cstr(struct rope *a, const char *b); +extern char *rope_cstr(struct rope *a); +extern int write_rope(struct rope *a); + +#endif diff --git a/rope.c b/rope.c new file mode 100644 --- /dev/null +++ b/rope.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2016-2017 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <jeffpc/rope.h> +#include <jeffpc/jeffpc.h> +#include <jeffpc/io.h> + +static struct rope_node *rope_node_alloc(struct str *str) +{ + struct rope_node *rn; + + rn = malloc(sizeof(struct rope_node)); + if (!rn) + return NULL; + + rn->str = str; + slist_init(&rn->node); + + return rn; +} + +static void rope_node_free(struct rope_node *rn) +{ + str_putref(rn->str); + free(rn); +} + +struct rope *rope_alloc(void) +{ + struct rope *rope; + + rope = malloc(sizeof(struct rope)); + if (!rope) + return NULL; + + slist_init(&rope->list); + rope->nodes = 0; + rope->len = 0; + + return rope; +} + +void rope_free(struct rope *rope) +{ + struct rope_node *rn, *tmp; + + slist_for_each_entry_safe(rn, tmp, &rope->list, node) + rope_node_free(rn); + + free(rope); +} + +/* move contents of b at the end of a */ +int rope_append_rope(struct rope *a, struct rope *b) +{ +#warning "move slist contents" + + a->nodes += b->nodes; + b->nodes = 0; + a->len += b->len; + b->len = 0; + + rope_free(b); + + return 0; +} + +int rope_append_str(struct rope *a, struct str *b) +{ + struct rope_node *rn; + + rn = rope_node_alloc(b); + if (!rn) + return -ENOMEM; + + slist_insert_tail(&a->list, &rn->node); + a->nodes++; + a->len += str_len(b); + + return 0; +} + +int rope_append_cstr(struct rope *a, const char *b) +{ + struct str *str; + + str = str_dup(b); + if (IS_ERR(str)) + return PTR_ERR(str); + + return rope_append_str(a, str); +} + +char *rope_cstr(struct rope *a) +{ + int ret; + + ret = rope_flatten(a); + if (ret) + return ERR_PTR(ret); + + /* no node - empty string */ + if (a->nodes == 0) + return NULL; + + VERIFY3U(a->nodes, ==, 1); + + /* one node - just return it */ + return str_cstr(slist_head_entry(&a->list, struct rope_node, node)->str); +} + +int rope_flatten(struct rope *rope) +{ + struct rope_node *rn; + struct str *str; + const char *tmp; + + if (rope->nodes <= 1) + return 0; + + tmp = malloc(rope->len + 1); + if (!tmp) + goto err; + + off = 0; + slist_for_each_entry(rn, &a->list, node) { + size_t slen = str_len(rn->str); + + memcpy(tmp + off, str_cstr(rn->str), slen); + + off += slen; + } + + ret[a->len] = '\0'; + + str = str_alloc(ret); + if (!str) + goto err_cstr; + + rn = rope_node_alloc(str); + if (!rn) + goto err_str; + + slist_for_each_entry_safe(rn, safe, &rope->list, node) + rope_node_free(rn); + + slist_ + + rope->nodes = 1; + + return ret; + +err_str: + str_putref(str); +err_cstr: + free(tmp); +err: + return -ENOMEM; +} + +int xwrite_rope(int fd, struct rope *a) +{ + struct rope_node *rn; + int ret; + + slist_for_each_entry(rn, &a->list, node) { + ret = xwrite_str(fd, str_cstr(rn->str)); + if (ret) + return ret; + } + + return 0; +}