Mercurial > libjeffpc
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,