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