xref: /dpdk/lib/telemetry/telemetry_json.h (revision daa02b5cddbb8e11b31d41e2bf7bb1ae64dcae2f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020 Intel Corporation
3  */
4 
5 #ifndef _RTE_TELEMETRY_JSON_H_
6 #define _RTE_TELEMETRY_JSON_H_
7 
8 #include <inttypes.h>
9 #include <stdarg.h>
10 #include <stdio.h>
11 #include <rte_common.h>
12 #include <rte_telemetry.h>
13 
14 /**
15  * @file
16  * Internal Telemetry Utility functions
17  *
18  * This file contains small inline functions to make it easier for applications
19  * to build up valid JSON responses to telemetry requests.
20  *
21  ***/
22 
23 /**
24  * @internal
25  * Copies a value into a buffer if the buffer has enough available space.
26  * Nothing written to buffer if an overflow ocurs.
27  * This function is not for use for values larger than given buffer length.
28  */
29 __rte_format_printf(3, 4)
30 static inline int
31 __json_snprintf(char *buf, const int len, const char *format, ...)
32 {
33 	char tmp[len];
34 	va_list ap;
35 	int ret;
36 
37 	va_start(ap, format);
38 	ret = vsnprintf(tmp, sizeof(tmp), format, ap);
39 	va_end(ap);
40 	if (ret > 0 && ret < (int)sizeof(tmp) && ret < len) {
41 		strcpy(buf, tmp);
42 		return ret;
43 	}
44 	return 0; /* nothing written or modified */
45 }
46 
47 /* Copies an empty array into the provided buffer. */
48 static inline int
49 rte_tel_json_empty_array(char *buf, const int len, const int used)
50 {
51 	return used + __json_snprintf(buf + used, len - used, "[]");
52 }
53 
54 /* Copies an empty object into the provided buffer. */
55 static inline int
56 rte_tel_json_empty_obj(char *buf, const int len, const int used)
57 {
58 	return used + __json_snprintf(buf + used, len - used, "{}");
59 }
60 
61 /* Copies a string into the provided buffer, in JSON format. */
62 static inline int
63 rte_tel_json_str(char *buf, const int len, const int used, const char *str)
64 {
65 	return used + __json_snprintf(buf + used, len - used, "\"%s\"", str);
66 }
67 
68 /* Appends a string into the JSON array in the provided buffer. */
69 static inline int
70 rte_tel_json_add_array_string(char *buf, const int len, const int used,
71 		const char *str)
72 {
73 	int ret, end = used - 1; /* strip off final delimiter */
74 	if (used <= 2) /* assume empty, since minimum is '[]' */
75 		return __json_snprintf(buf, len, "[\"%s\"]", str);
76 
77 	ret = __json_snprintf(buf + end, len - end, ",\"%s\"]", str);
78 	return ret == 0 ? used : end + ret;
79 }
80 
81 /* Appends an integer into the JSON array in the provided buffer. */
82 static inline int
83 rte_tel_json_add_array_int(char *buf, const int len, const int used, int val)
84 {
85 	int ret, end = used - 1; /* strip off final delimiter */
86 	if (used <= 2) /* assume empty, since minimum is '[]' */
87 		return __json_snprintf(buf, len, "[%d]", val);
88 
89 	ret = __json_snprintf(buf + end, len - end, ",%d]", val);
90 	return ret == 0 ? used : end + ret;
91 }
92 
93 /* Appends a uint64_t into the JSON array in the provided buffer. */
94 static inline int
95 rte_tel_json_add_array_u64(char *buf, const int len, const int used,
96 		uint64_t val)
97 {
98 	int ret, end = used - 1; /* strip off final delimiter */
99 	if (used <= 2) /* assume empty, since minimum is '[]' */
100 		return __json_snprintf(buf, len, "[%"PRIu64"]", val);
101 
102 	ret = __json_snprintf(buf + end, len - end, ",%"PRIu64"]", val);
103 	return ret == 0 ? used : end + ret;
104 }
105 
106 /*
107  * Add a new element with raw JSON value to the JSON array stored in the
108  * provided buffer.
109  */
110 static inline int
111 rte_tel_json_add_array_json(char *buf, const int len, const int used,
112 		const char *str)
113 {
114 	int ret, end = used - 1; /* strip off final delimiter */
115 	if (used <= 2) /* assume empty, since minimum is '[]' */
116 		return __json_snprintf(buf, len, "[%s]", str);
117 
118 	ret = __json_snprintf(buf + end, len - end, ",%s]", str);
119 	return ret == 0 ? used : end + ret;
120 }
121 
122 /**
123  * Add a new element with uint64_t value to the JSON object stored in the
124  * provided buffer.
125  */
126 static inline int
127 rte_tel_json_add_obj_u64(char *buf, const int len, const int used,
128 		const char *name, uint64_t val)
129 {
130 	int ret, end = used - 1;
131 	if (used <= 2) /* assume empty, since minimum is '{}' */
132 		return __json_snprintf(buf, len, "{\"%s\":%"PRIu64"}", name,
133 				val);
134 
135 	ret = __json_snprintf(buf + end, len - end, ",\"%s\":%"PRIu64"}",
136 			name, val);
137 	return ret == 0 ? used : end + ret;
138 }
139 
140 /**
141  * Add a new element with int value to the JSON object stored in the
142  * provided buffer.
143  */
144 static inline int
145 rte_tel_json_add_obj_int(char *buf, const int len, const int used,
146 		const char *name, int val)
147 {
148 	int ret, end = used - 1;
149 	if (used <= 2) /* assume empty, since minimum is '{}' */
150 		return __json_snprintf(buf, len, "{\"%s\":%d}", name,
151 				val);
152 
153 	ret = __json_snprintf(buf + end, len - end, ",\"%s\":%d}",
154 			name, val);
155 	return ret == 0 ? used : end + ret;
156 }
157 
158 /**
159  * Add a new element with string value to the JSON object stored in the
160  * provided buffer.
161  */
162 static inline int
163 rte_tel_json_add_obj_str(char *buf, const int len, const int used,
164 		const char *name, const char *val)
165 {
166 	int ret, end = used - 1;
167 	if (used <= 2) /* assume empty, since minimum is '{}' */
168 		return __json_snprintf(buf, len, "{\"%s\":\"%s\"}", name, val);
169 
170 	ret = __json_snprintf(buf + end, len - end, ",\"%s\":\"%s\"}",
171 			name, val);
172 	return ret == 0 ? used : end + ret;
173 }
174 
175 /**
176  * Add a new element with raw JSON value to the JSON object stored in the
177  * provided buffer.
178  */
179 static inline int
180 rte_tel_json_add_obj_json(char *buf, const int len, const int used,
181 		const char *name, const char *val)
182 {
183 	int ret, end = used - 1;
184 	if (used <= 2) /* assume empty, since minimum is '{}' */
185 		return __json_snprintf(buf, len, "{\"%s\":%s}", name, val);
186 
187 	ret = __json_snprintf(buf + end, len - end, ",\"%s\":%s}",
188 			name, val);
189 	return ret == 0 ? used : end + ret;
190 }
191 
192 #endif /*_RTE_TELEMETRY_JSON_H_*/
193