changeset 709:c562ff6e48d3

val: remove duplicate & inefficient packing implementation We now rely the backends providing a single function to pack a whole struct val. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Tue, 19 Mar 2019 12:20:22 -0400
parents 9a1c3e578c26
children 473a2904ef50
files CMakeLists.txt val_fmt_cbor.c val_fmt_json.c val_impl_packing.h val_pack.c
diffstat 5 files changed, 10 insertions(+), 331 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Tue Mar 19 12:12:54 2019 -0400
+++ b/CMakeLists.txt	Tue Mar 19 12:20:22 2019 -0400
@@ -133,8 +133,6 @@
 	val.c
 	val_array.c
 	val_dump.c
-	val_fmt_cbor.c
-	val_fmt_json.c
 	val_nvl.c
 	val_pack.c
 	val_unpack.c
--- a/val_fmt_cbor.c	Tue Mar 19 12:12:54 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2017-2019 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/nvl.h>
-#include <jeffpc/cbor.h>
-
-#include "val_impl_packing.h"
-
-/*
- * nvl packing interface
- */
-
-const struct valops valops_cbor = {
-	.pack_val = cbor_pack_val,
-};
--- a/val_fmt_json.c	Tue Mar 19 12:12:54 2019 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2017-2019 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/nvl.h>
-#include <jeffpc/json.h>
-
-#include "val_impl_packing.h"
-
-const struct valops valops_json = {
-	.pack_val = json_pack_val,
-};
--- a/val_impl_packing.h	Tue Mar 19 12:12:54 2019 -0400
+++ b/val_impl_packing.h	Tue Mar 19 12:20:22 2019 -0400
@@ -25,100 +25,21 @@
 
 #include <jeffpc/nvl.h>
 #include <jeffpc/buffer.h>
-
-#define CALL(ops, op, args)						\
-	({								\
-		int _ret = 0;						\
-									\
-		if ((ops)->op)						\
-			_ret = (ops)->op args;				\
-									\
-		_ret;							\
-	 })
-
-#define CALL_OR_FAIL(ops, op, args)					\
-	({								\
-		int _ret = -ENOTSUP;					\
-									\
-		if ((ops)->op)						\
-			_ret = (ops)->op args;				\
-									\
-		_ret;							\
-	 })
-
-/*
- * Packing operations
- *
- * A required function pointer is only required when an item of that type
- * must be encoded.  For example, if an encoder doesn't implement packing of
- * strings, packing of all strings vals will fail because of this limitation.
- * Packing of other (non string) vals may or may not fail for
- * other reasons.
- */
-struct packops {
-	/*
-	 * top-level encoder hooks
-	 *
-	 * Optional: All.
-	 */
-	int (*buffer_finish)(struct buffer *buffer);
+#include <jeffpc/cbor.h>
+#include <jeffpc/json.h>
 
-	/*
-	 * nvlist encoders
-	 *
-	 * Required: At least one of prologue or epilogue.
-	 * Optional: The rest.
-	 */
-	int (*nvl_prologue)(struct buffer *buffer, struct nvlist *nvl);
-	int (*nvl_name_sep)(struct buffer *buffer, const struct nvpair *pair);
-	int (*nvl_val_sep)(struct buffer *buffer, const struct nvpair *pair);
-	int (*nvl_epilogue)(struct buffer *buffer, struct nvlist *nvl);
-
-	/*
-	 * array encoders
-	 *
-	 * Required: At least one of prologue or epilogue.
-	 * Optional: The rest.
-	 */
-	int (*array_prologue)(struct buffer *buffer, struct val *const *vals,
-			      size_t nelem);
-	int (*array_val_sep)(struct buffer *buffer, const struct val *val);
-	int (*array_epilogue)(struct buffer *buffer, struct val *const *vals,
-			      size_t nelem);
-
-	/*
-	 * nvpair
-	 *
-	 * Optional: All.
-	 */
-	int (*pair_prologue)(struct buffer *buffer, const struct nvpair *pair);
-	int (*pair_epilogue)(struct buffer *buffer, const struct nvpair *pair);
-
-	/*
-	 * value encoders
-	 *
-	 * Required: All.
-	 */
-	int (*val_blob)(struct buffer *buffer, const void *data, size_t size);
-	int (*val_bool)(struct buffer *buffer, bool b);
-	int (*val_int)(struct buffer *buffer, uint64_t i);
-	int (*val_null)(struct buffer *buffer);
-	int (*val_str)(struct buffer *buffer, const char *str);
+struct valops {
+	int (*pack)(struct buffer *buffer, struct val *val);
 };
 
-struct unpackops {
-	/* TODO */
+static const struct valops valops_cbor = {
+	.pack = cbor_pack_val,
 };
 
-struct valops {
-	int (*pack_val)(struct buffer *buffer, struct val *val);
-	const struct packops pack;
-	const struct unpackops unpack;
+static const struct valops valops_json = {
+	.pack = json_pack_val,
 };
 
-extern const struct valops valops_cbor;
-extern const struct valops valops_json;
-
 static inline const struct valops *select_ops(enum val_format format)
 {
 	switch (format) {
--- a/val_pack.c	Tue Mar 19 12:12:54 2019 -0400
+++ b/val_pack.c	Tue Mar 19 12:20:22 2019 -0400
@@ -25,192 +25,16 @@
 
 #include "val_impl_packing.h"
 
-static int pack_nvl(const struct packops *ops, struct buffer *buffer,
-		    struct nvlist *nvl);
-static int pack_val(const struct packops *ops, struct buffer *buffer,
-		    struct val *val);
-
-static int pack_array(const struct packops *ops, struct buffer *buffer,
-		      struct val **vals, size_t nelem)
-{
-	bool first = true;
-	size_t i;
-	int ret;
-
-	if (!ops->array_prologue && !ops->array_epilogue)
-		return -ENOTSUP;
-
-	if ((ret = CALL(ops, array_prologue, (buffer, vals, nelem))))
-		return ret;
-
-	for (i = 0; i < nelem; i++) {
-		struct val *val = vals[i];
-
-		if (first) {
-			first = false;
-			if ((ret = CALL(ops, array_val_sep, (buffer, val))))
-				return ret;
-		}
-
-		if ((ret = pack_val(ops, buffer, val)))
-			return ret;
-	}
-
-	if ((ret = CALL(ops, array_epilogue, (buffer, vals, nelem))))
-		return ret;
-
-	return 0;
-}
-
-static int pack_blob(const struct packops *ops, struct buffer *buffer,
-		     const void *data, size_t size)
-{
-	return CALL_OR_FAIL(ops, val_blob, (buffer, data, size));
-}
-
-static int pack_bool(const struct packops *ops, struct buffer *buffer,
-		     bool b)
-{
-	return CALL_OR_FAIL(ops, val_bool, (buffer, b));
-}
-
-static int pack_int(const struct packops *ops, struct buffer *buffer,
-		    uint64_t i)
-{
-	return CALL_OR_FAIL(ops, val_int, (buffer, i));
-}
-
-static int pack_null(const struct packops *ops, struct buffer *buffer)
-{
-	return CALL_OR_FAIL(ops, val_null, (buffer));
-}
-
-static int pack_string(const struct packops *ops, struct buffer *buffer,
-		       struct str *str)
-{
-	const char *s;
-
-	/*
-	 * Even though we try to avoid NULL pointers to indicate empty
-	 * strings, they can crop up from many places.  So, it is safer to
-	 * do the check here.
-	 */
-	s = str ? str_cstr(str) : "";
-
-	return CALL_OR_FAIL(ops, val_str, (buffer, s));
-}
-
-static int pack_val(const struct packops *ops, struct buffer *buffer,
-		    struct val *val)
-{
-	int ret = -ENOTSUP;
-
-	switch (val->type) {
-		case VT_ARRAY:
-			ret = pack_array(ops, buffer, val->array.vals,
-					 val->array.nelem);
-			break;
-		case VT_BLOB:
-			ret = pack_blob(ops, buffer, val->blob.ptr,
-					val->blob.size);
-			break;
-		case VT_BOOL:
-			ret = pack_bool(ops, buffer, val->b);
-			break;
-		case VT_INT:
-			ret = pack_int(ops, buffer, val->i);
-			break;
-		case VT_NULL:
-			ret = pack_null(ops, buffer);
-			break;
-		case VT_NVL:
-			ret = pack_nvl(ops, buffer, val_cast_to_nvl(val));
-			break;
-		case VT_STR:
-			ret = pack_string(ops, buffer, val_cast_to_str(val));
-			break;
-		case VT_SYM:
-		case VT_CONS:
-		case VT_CHAR:
-			/* not supported */
-			break;
-	}
-
-	return ret;
-}
-
-static int pack_pair(const struct packops *ops, struct buffer *buffer,
-		     const struct nvpair *pair)
-{
-	int ret;
-
-	if ((ret = CALL(ops, pair_prologue, (buffer, pair))))
-		return ret;
-
-	if ((ret = pack_string(ops, buffer, pair->name)))
-		return ret;
-
-	if ((ret = CALL(ops, nvl_name_sep, (buffer, pair))))
-		return ret;
-
-	if ((ret = pack_val(ops, buffer, pair->value)))
-		return ret;
-
-	if ((ret = CALL(ops, pair_epilogue, (buffer, pair))))
-		return ret;
-
-	return 0;
-}
-
-static int pack_nvl(const struct packops *ops, struct buffer *buffer,
-		    struct nvlist *nvl)
-{
-	const struct nvpair *pair;
-	bool first = true;
-	int ret;
-
-	if (!ops->nvl_prologue && !ops->nvl_epilogue)
-		return -ENOTSUP;
-
-	if ((ret = CALL(ops, nvl_prologue, (buffer, nvl))))
-		return ret;
-
-	nvl_for_each(pair, nvl) {
-		if (first) {
-			first = false;
-		} else {
-			if ((ret = CALL(ops, nvl_val_sep, (buffer, pair))))
-				return ret;
-		}
-
-		if ((ret = pack_pair(ops, buffer, pair)))
-			return ret;
-	}
-
-	if ((ret = CALL(ops, nvl_epilogue, (buffer, nvl))))
-		return ret;
-
-	return 0;
-}
-
 static int do_val_pack(struct buffer *buffer, struct val *val,
 		       enum val_format format)
 {
 	const struct valops *ops;
-	int ret;
 
 	ops = select_ops(format);
-	if (!ops)
+	if (!ops || !ops->pack)
 		return -ENOTSUP;
 
-	if (ops->pack_val)
-		return ops->pack_val(buffer, val);
-
-	ret = pack_val(&ops->pack, buffer, val);
-	if (ret)
-		return ret;
-
-	return CALL(&ops->pack, buffer_finish, (buffer));
+	return ops->pack(buffer, val);
 }
 
 ssize_t val_pack_into(struct val *val, void *buf, size_t bufsize,