From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from dpdk.org (dpdk.org [92.243.14.124])
	by inbox.dpdk.org (Postfix) with ESMTP id 18E9FA0597;
	Wed,  8 Apr 2020 19:09:31 +0200 (CEST)
Received: from [92.243.14.124] (localhost [127.0.0.1])
	by dpdk.org (Postfix) with ESMTP id F0F541C1B7;
	Wed,  8 Apr 2020 19:08:19 +0200 (CEST)
Received: from mga14.intel.com (mga14.intel.com [192.55.52.115])
 by dpdk.org (Postfix) with ESMTP id 82D321C1A9
 for <dev@dpdk.org>; Wed,  8 Apr 2020 19:08:17 +0200 (CEST)
IronPort-SDR: 0pQlzp4MZjmyuL7dVA8YqCzKBD/4rpIqxkeB67hiubQ2X6PPQG+eBE1tufOERGIgU8dBq+Hhdo
 qOUMQXSMhdMQ==
X-Amp-Result: SKIPPED(no attachment in message)
X-Amp-File-Uploaded: False
Received: from fmsmga006.fm.intel.com ([10.253.24.20])
 by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;
 08 Apr 2020 10:08:17 -0700
IronPort-SDR: 2urAisCo/MyBmQZJthVK5UeBUWp48XbeAzNH88V2Y7QuRcrW/bgWWHsJwoNZXTyu8mcHiqaEn0
 TmyHVdzgh/mQ==
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.72,359,1580803200"; d="scan'208";a="452880208"
Received: from silpixa00399953.ir.intel.com (HELO
 silpixa00399953.ger.corp.intel.com) ([10.237.222.53])
 by fmsmga006.fm.intel.com with ESMTP; 08 Apr 2020 10:08:15 -0700
From: Ciara Power <ciara.power@intel.com>
To: dev@dpdk.org,
	kevin.laatz@intel.com
Cc: reshma.pattan@intel.com, jerinjacobk@gmail.com, david.marchand@redhat.com,
 keith.wiles@intel.com, mb@smartsharesystems.com, thomas@monjalon.net,
 Bruce Richardson <bruce.richardson@intel.com>
Date: Wed,  8 Apr 2020 17:49:46 +0100
Message-Id: <20200408164956.47864-7-ciara.power@intel.com>
X-Mailer: git-send-email 2.17.1
In-Reply-To: <20200408164956.47864-1-ciara.power@intel.com>
References: <20200319171907.60891-1-ciara.power@intel.com>
 <20200408164956.47864-1-ciara.power@intel.com>
Subject: [dpdk-dev] [PATCH v2 06/16] telemetry: add utility functions for
	creating json
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org
Sender: "dev" <dev-bounces@dpdk.org>

From: Bruce Richardson <bruce.richardson@intel.com>

The functions added in this patch will make it easier for applications
to build up correct JSON responses to telemetry requests.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
---
 lib/librte_telemetry/Makefile             |   1 +
 lib/librte_telemetry/meson.build          |   2 +-
 lib/librte_telemetry/rte_telemetry.h      |   1 +
 lib/librte_telemetry/rte_telemetry_json.h | 205 ++++++++++++++++++++++
 4 files changed, 208 insertions(+), 1 deletion(-)
 create mode 100644 lib/librte_telemetry/rte_telemetry_json.h

diff --git a/lib/librte_telemetry/Makefile b/lib/librte_telemetry/Makefile
index 74a6e2d2f7..9012156c1b 100644
--- a/lib/librte_telemetry/Makefile
+++ b/lib/librte_telemetry/Makefile
@@ -29,5 +29,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_TELEMETRY) += telemetry.c
 
 # export include files
 SYMLINK-$(CONFIG_RTE_LIBRTE_TELEMETRY)-include := rte_telemetry.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_TELEMETRY)-include += rte_telemetry_json.h
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_telemetry/meson.build b/lib/librte_telemetry/meson.build
index 710c119b7a..cc0cdeb5f6 100644
--- a/lib/librte_telemetry/meson.build
+++ b/lib/librte_telemetry/meson.build
@@ -5,7 +5,7 @@ includes = [global_inc]
 
 sources = files('rte_telemetry.c', 'rte_telemetry_parser.c', 'rte_telemetry_parser_test.c',
 	'telemetry.c')
-headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_parser.h')
+headers = files('rte_telemetry.h', 'rte_telemetry_internal.h', 'rte_telemetry_parser.h', 'rte_telemetry_json.h')
 cflags += '-DALLOW_EXPERIMENTAL_API'
 includes += include_directories('../librte_metrics')
 
diff --git a/lib/librte_telemetry/rte_telemetry.h b/lib/librte_telemetry/rte_telemetry.h
index d0230d4544..8b3df04292 100644
--- a/lib/librte_telemetry/rte_telemetry.h
+++ b/lib/librte_telemetry/rte_telemetry.h
@@ -4,6 +4,7 @@
 
 #include <stdint.h>
 #include <rte_compat.h>
+#include <rte_telemetry_json.h>
 
 #ifndef _RTE_TELEMETRY_H_
 #define _RTE_TELEMETRY_H_
diff --git a/lib/librte_telemetry/rte_telemetry_json.h b/lib/librte_telemetry/rte_telemetry_json.h
new file mode 100644
index 0000000000..02fcafc73a
--- /dev/null
+++ b/lib/librte_telemetry/rte_telemetry_json.h
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#ifndef _RTE_TELEMETRY_JSON_H_
+#define _RTE_TELEMETRY_JSON_H_
+
+#include <inttypes.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: all functions in this file may change without prior notice
+ *
+ * @file
+ * RTE Telemetry Utility Functions for Creating JSON Responses
+ *
+ * This file contains small inline functions to make it easier for applications
+ * to build up valid JSON responses to telemetry requests.
+ *
+ ***/
+
+/**
+ * @internal
+ *
+ * Copies a value into a buffer if the buffer has enough available space.
+ * Nothing written to buffer if an overflow ocurs.
+ * This function is not for use for values larger than 1k.
+ *
+ * @param buf
+ * Buffer for data to be appended to.
+ * @param len
+ * Length of buffer.
+ * @param format
+ * Format string.
+ * @param ...
+ * Optional arguments that may be required by the format string.
+ *
+ * @return
+ *  Number of characters added to buffer
+ */
+__attribute__((__format__(__printf__, 3, 4)))
+static inline int
+__json_snprintf(char *buf, const int len, const char *format, ...)
+{
+	char tmp[1024];
+	va_list ap;
+	int ret;
+
+	va_start(ap, format);
+	ret = vsnprintf(tmp, sizeof(tmp), format, ap);
+	va_end(ap);
+	if (ret > 0 && ret < (int)sizeof(tmp) && ret < len) {
+		strcpy(buf, tmp);
+		return ret;
+	}
+	return 0; /* nothing written or modified */
+}
+
+/**
+ * Copies an empty array into the provided buffer.
+ *
+ * @param buf
+ * Buffer to hold the empty array.
+ * @param len
+ * Length of buffer.
+ * @param used
+ * The number of used characters in the buffer.
+ *
+ * @return
+ *  Total number of characters in buffer.
+ */
+static inline int
+rte_tel_json_empty_array(char *buf, const int len, const int used)
+{
+	return used + __json_snprintf(buf + used, len - used, "[]");
+}
+
+/**
+ * Copies an empty object into the provided buffer.
+ *
+ * @param buf
+ * Buffer to hold the empty object.
+ * @param len
+ * Length of buffer.
+ * @param used
+ * The number of used characters in the buffer.
+ *
+ * @return
+ *  Total number of characters in buffer
+ */
+static inline int
+rte_tel_json_empty_obj(char *buf, const int len, const int used)
+{
+	return used + __json_snprintf(buf + used, len - used, "{}");
+}
+
+/**
+ * Copies a string into the provided buffer, in JSON format.
+ *
+ * @param buf
+ * Buffer to copy string into.
+ * @param len
+ * Length of buffer.
+ * @param used
+ * The number of used characters in the buffer.
+ * @param str
+ * String value to copy into buffer.
+ *
+ * @return
+ *  Total number of characters in buffer
+ */
+static inline int
+rte_tel_json_str(char *buf, const int len, const int used, const char *str)
+{
+	return used + __json_snprintf(buf + used, len - used, "\"%s\"", str);
+}
+
+/**
+ * Appends a string into the JSON array in the provided buffer.
+ *
+ * @param buf
+ * Buffer to append array string to.
+ * @param len
+ * Length of buffer.
+ * @param used
+ * The number of used characters in the buffer.
+ * @param str
+ * String value to append to buffer.
+ *
+ * @return
+ *  Total number of characters in buffer
+ */
+static inline int
+rte_tel_json_add_array_string(char *buf, const int len, const int used,
+		const char *str)
+{
+	int ret, end = used - 1; /* strip off final delimiter */
+	if (used <= 2) /* assume empty, since minimum is '[]' */
+		return __json_snprintf(buf, len, "[\"%s\"]", str);
+
+	ret = __json_snprintf(buf + end, len - end, ",\"%s\"]", str);
+	return ret == 0 ? used : end + ret;
+}
+
+/**
+ * Appends an integer into the JSON array in the provided buffer.
+ *
+ * @param buf
+ * Buffer to append array integer to.
+ * @param len
+ * Length of buffer.
+ * @param used
+ * The number of used characters in the buffer.
+ * @param val
+ * Integer value to append to buffer.
+ *
+ * @return
+ *  Total number of characters in buffer
+ */
+static inline int
+rte_tel_json_add_array_int(char *buf, const int len, const int used, int val)
+{
+	int ret, end = used - 1; /* strip off final delimiter */
+	if (used <= 2) /* assume empty, since minimum is '[]' */
+		return __json_snprintf(buf, len, "[%d]", val);
+
+	ret = __json_snprintf(buf + end, len - end, ",%d]", val);
+	return ret == 0 ? used : end + ret;
+}
+
+/**
+ * Add a new element with uint64_t value to the JSON object stored in the
+ * provided buffer.
+ *
+ * @param buf
+ * Buffer to append object element to.
+ * @param len
+ * Length of buffer.
+ * @param used
+ * The number of used characters in the buffer.
+ * @param name
+ * String for object element key.
+ * @param val
+ * Uint64_t for object element value.
+ *
+ * @return
+ *  Total number of characters in buffer
+ */
+static inline int
+rte_tel_json_add_obj_u64(char *buf, const int len, const int used,
+		const char *name, uint64_t val)
+{
+	int ret, end = used - 1;
+	if (used <= 2) /* assume empty, since minimum is '{}' */
+		return __json_snprintf(buf, len, "{\"%s\":%"PRIu64"}", name,
+				val);
+
+	ret = __json_snprintf(buf + end, len - end, ",\"%s\":%"PRIu64"}",
+			name, val);
+	return ret == 0 ? used : end + ret;
+}
+
+#endif /*_RTE_TELEMETRY_JSON_H_*/
-- 
2.17.1