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;
+}