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 occurs.
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
__json_snprintf(char * buf,const int len,const char * format,...)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
rte_tel_json_empty_array(char * buf,const int len,const int used)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
rte_tel_json_empty_obj(char * buf,const int len,const int used)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
rte_tel_json_str(char * buf,const int len,const int used,const char * str)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
rte_tel_json_add_array_string(char * buf,const int len,const int used,const char * str)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
rte_tel_json_add_array_int(char * buf,const int len,const int used,int val)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
rte_tel_json_add_array_u64(char * buf,const int len,const int used,uint64_t val)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
rte_tel_json_add_array_json(char * buf,const int len,const int used,const char * str)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
rte_tel_json_add_obj_u64(char * buf,const int len,const int used,const char * name,uint64_t val)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
rte_tel_json_add_obj_int(char * buf,const int len,const int used,const char * name,int val)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
rte_tel_json_add_obj_str(char * buf,const int len,const int used,const char * name,const char * val)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
rte_tel_json_add_obj_json(char * buf,const int len,const int used,const char * name,const char * val)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