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