changeset 683:b3a4ac14a22d

cbor: add a function to peek at current data item Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Thu, 11 Oct 2018 14:20:08 -0400
parents 117603444601
children 41a3427cde1d
files fmt_cbor.c include/jeffpc/cbor.h mapfile-vers tests/.hgignore tests/CMakeLists.txt tests/test_cbor_peek_type.c
diffstat 6 files changed, 181 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/fmt_cbor.c	Tue Apr 17 20:17:14 2018 -0400
+++ b/fmt_cbor.c	Thu Oct 11 14:20:08 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * 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
@@ -59,6 +59,10 @@
 			(type << 5) | additional;			\
 		})
 
+/*
+ * pack
+ */
+
 static int pack_cbor_type_byte(struct buffer *buffer, enum major_type type,
 			       uint8_t additional)
 {
@@ -299,3 +303,59 @@
 
 	return -ENOTSUP;
 }
+
+/*
+ * peek
+ */
+
+int cbor_peek_type(struct buffer *buffer, enum val_type *type)
+{
+	const uint8_t *ptr;
+	enum major_type major_type;
+	uint8_t extra;
+
+	if (buffer_remain(buffer) < 1)
+		return -EFAULT;
+
+	ptr = buffer_data_current(buffer);
+
+	major_type = *ptr >> 5;
+	extra = *ptr & 0x1f;
+
+	switch (major_type) {
+		case CMT_UINT:
+			*type = VT_INT;
+			break;
+		case CMT_BYTE:
+			*type = VT_BLOB;
+			break;
+		case CMT_TEXT:
+			*type = VT_STR;
+			break;
+		case CMT_FLOAT:
+			switch (extra) {
+				case ADDL_FLOAT_FALSE:
+				case ADDL_FLOAT_TRUE:
+					*type = VT_BOOL;
+					break;
+				case ADDL_FLOAT_NULL:
+					*type = VT_NULL;
+					break;
+				case ADDL_FLOAT_BREAK:
+				default:
+					return -ENOTSUP;
+			}
+			break;
+		case CMT_ARRAY:
+			*type = VT_ARRAY;
+			break;
+		case CMT_MAP:
+			*type = VT_NVL;
+			break;
+		case CMT_NINT:
+		case CMT_TAG:
+			return -ENOTSUP;
+	}
+
+	return 0;
+}
--- a/include/jeffpc/cbor.h	Tue Apr 17 20:17:14 2018 -0400
+++ b/include/jeffpc/cbor.h	Thu Oct 11 14:20:08 2018 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
+ * 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
@@ -56,4 +56,6 @@
 	return cbor_pack_cstr_len(buffer, str, strlen(str));
 }
 
+extern int cbor_peek_type(struct buffer *buffer, enum val_type *type);
+
 #endif
--- a/mapfile-vers	Tue Apr 17 20:17:14 2018 -0400
+++ b/mapfile-vers	Thu Oct 11 14:20:08 2018 -0400
@@ -64,6 +64,7 @@
 		cbor_pack_str;
 		cbor_pack_uint;
 		cbor_pack_val;
+		cbor_peek_type;
 
 		# cstr
 		strcpy_safe;
--- a/tests/.hgignore	Tue Apr 17 20:17:14 2018 -0400
+++ b/tests/.hgignore	Thu Oct 11 14:20:08 2018 -0400
@@ -6,6 +6,7 @@
 test_bswap
 test_buffer
 test_cbor_pack
+test_cbor_peek_type
 test_container_of
 test_endian
 test_errno
--- a/tests/CMakeLists.txt	Tue Apr 17 20:17:14 2018 -0400
+++ b/tests/CMakeLists.txt	Thu Oct 11 14:20:08 2018 -0400
@@ -31,6 +31,7 @@
 build_test_bin_and_run(atomic-single-thread)
 build_test_bin_and_run(bswap)
 build_test_bin_and_run(buffer)
+build_test_bin_and_run(cbor_peek_type)
 build_test_bin_and_run(container_of)
 build_test_bin_and_run(endian)
 build_test_bin_and_run(errno)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test_cbor_peek_type.c	Thu Oct 11 14:20:08 2018 -0400
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 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/cbor.h>
+
+#include "test.c"
+
+static const struct test {
+	int ret;
+	enum val_type type;
+} tests[256] = {
+#define V1(idx, ret, type)	[idx] = { (ret), (type) }
+#define V2(idx, ret, type)	V1((idx),     (ret), (type)), \
+				V1((idx) + 1, (ret), (type))
+#define V4(idx, ret, type)	V2((idx),     (ret), (type)), \
+				V2((idx) + 2, (ret), (type))
+#define V8(idx, ret, type)	V4((idx),     (ret), (type)), \
+				V4((idx) + 4, (ret), (type))
+#define V16(idx, ret, type)	V8((idx),     (ret), (type)), \
+				V8((idx) + 8, (ret), (type))
+#define V32(idx, ret, type)	V16((idx),     (ret), (type)), \
+				V16((idx) + 16, (ret), (type))
+
+	V32(0x00, 0,        VT_INT),	/* CMT_UINT */
+	V32(0x20, -ENOTSUP, 0),		/* CMT_NINT */
+	V32(0x40, 0,        VT_BLOB),	/* CMT_BYTE */
+	V32(0x60, 0,        VT_STR),	/* CMT_TEXT */
+	V32(0x80, 0,        VT_ARRAY),	/* CMT_ARRAY */
+	V32(0xa0, 0,        VT_NVL),    /* CMT_MAP */
+	V32(0xc0, -ENOTSUP, 0),		/* CMT_TAG */
+
+	/* CMT_FLOAT is more complicated */
+	V16(0xe0, -ENOTSUP, 0),		/* CMT_FLOAT */
+	V4 (0xf0, -ENOTSUP, 0),		/* CMT_FLOAT */
+	V2 (0xf4, 0,        VT_BOOL),	/* CMT_FLOAT => bool */
+	V1 (0xf6, 0,        VT_NULL),	/* CMT_FLOAT => null */
+	V1 (0xf7, -ENOTSUP, 0),		/* CMT_FLOAT */
+	V4 (0xf8, -ENOTSUP, 0),		/* CMT_FLOAT */
+	V2 (0xfc, -ENOTSUP, 0),		/* CMT_FLOAT */
+	V1 (0xfe, -ENOTSUP, 0),		/* CMT_FLOAT */
+	V1 (0xff, -ENOTSUP, 0),		/* CMT_FLOAT => break */
+};
+
+static void test_zero(void)
+{
+	enum val_type type;
+	struct buffer buf;
+	int ret;
+
+	fprintf(stderr, "empty input: expecting -EFAULT...");
+
+	buffer_init_static(&buf, NULL, 0, false);
+
+	ret = cbor_peek_type(&buf, &type);
+
+	check_rets(-EFAULT, ret, "cbor_peek_type()");
+
+	fprintf(stderr, "ok.\n");
+}
+
+static void test_one(void)
+{
+	size_t i;
+
+	for (i = 0; i < ARRAY_LEN(tests); i++) {
+		const struct test *run = &tests[i];
+		struct buffer buf;
+		enum val_type type;
+		uint8_t in;
+		int ret;
+
+		fprintf(stderr, "%3zu: %02x expecting ret=%d (%s) type=%s...",
+			i, i, run->ret, xstrerror(run->ret),
+			val_typename(run->type));
+
+		in = i;
+
+		buffer_init_static(&buf, &in, sizeof(in), false);
+
+		ret = cbor_peek_type(&buf, &type);
+
+		check_rets(run->ret, ret, "cbor_peek_type()");
+
+		if (!ret && (type != run->type))
+			fail("got %s", val_typename(type));
+
+		fprintf(stderr, "ok.\n");
+	}
+}
+
+void test(void)
+{
+	test_zero();
+	test_one();
+}