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