buffer.h 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #ifndef NETDATA_WEB_BUFFER_H
  3. #define NETDATA_WEB_BUFFER_H 1
  4. #include "../string/utf8.h"
  5. #include "../libnetdata.h"
  6. #ifdef ENABLE_H2O
  7. #include "h2o/memory.h"
  8. #endif
  9. #define WEB_DATA_LENGTH_INCREASE_STEP 1024
  10. #define BUFFER_JSON_MAX_DEPTH 32 // max is 255
  11. extern const char hex_digits[16];
  12. extern const char base64_digits[64];
  13. extern unsigned char hex_value_from_ascii[256];
  14. extern unsigned char base64_value_from_ascii[256];
  15. typedef enum __attribute__ ((__packed__)) {
  16. BUFFER_JSON_EMPTY = 0,
  17. BUFFER_JSON_OBJECT,
  18. BUFFER_JSON_ARRAY,
  19. } BUFFER_JSON_NODE_TYPE;
  20. typedef struct web_buffer_json_node {
  21. BUFFER_JSON_NODE_TYPE type;
  22. uint32_t count:24;
  23. } BUFFER_JSON_NODE;
  24. #define BUFFER_QUOTE_MAX_SIZE 7
  25. typedef enum __attribute__ ((__packed__)) {
  26. WB_CONTENT_CACHEABLE = (1 << 0),
  27. WB_CONTENT_NO_CACHEABLE = (1 << 1),
  28. } BUFFER_OPTIONS;
  29. typedef enum __attribute__ ((__packed__)) {
  30. CT_NONE = 0,
  31. CT_APPLICATION_JSON,
  32. CT_TEXT_PLAIN,
  33. CT_TEXT_HTML,
  34. CT_APPLICATION_X_JAVASCRIPT,
  35. CT_TEXT_CSS,
  36. CT_TEXT_XML,
  37. CT_APPLICATION_XML,
  38. CT_TEXT_XSL,
  39. CT_APPLICATION_OCTET_STREAM,
  40. CT_APPLICATION_X_FONT_TRUETYPE,
  41. CT_APPLICATION_X_FONT_OPENTYPE,
  42. CT_APPLICATION_FONT_WOFF,
  43. CT_APPLICATION_FONT_WOFF2,
  44. CT_APPLICATION_VND_MS_FONTOBJ,
  45. CT_IMAGE_SVG_XML,
  46. CT_IMAGE_PNG,
  47. CT_IMAGE_JPG,
  48. CT_IMAGE_GIF,
  49. CT_IMAGE_XICON,
  50. CT_IMAGE_ICNS,
  51. CT_IMAGE_BMP,
  52. CT_PROMETHEUS,
  53. CT_AUDIO_MPEG,
  54. CT_AUDIO_OGG,
  55. CT_VIDEO_MP4,
  56. CT_APPLICATION_PDF,
  57. CT_APPLICATION_ZIP,
  58. } HTTP_CONTENT_TYPE;
  59. typedef struct web_buffer {
  60. size_t size; // allocation size of buffer, in bytes
  61. size_t len; // current data length in buffer, in bytes
  62. char *buffer; // the buffer itself
  63. HTTP_CONTENT_TYPE content_type; // the content type of the data in the buffer
  64. BUFFER_OPTIONS options; // options related to the content
  65. time_t date; // the timestamp this content has been generated
  66. time_t expires; // the timestamp this content expires
  67. size_t *statistics;
  68. struct {
  69. char key_quote[BUFFER_QUOTE_MAX_SIZE + 1];
  70. char value_quote[BUFFER_QUOTE_MAX_SIZE + 1];
  71. int8_t depth;
  72. bool minify;
  73. BUFFER_JSON_NODE stack[BUFFER_JSON_MAX_DEPTH];
  74. } json;
  75. } BUFFER;
  76. #define buffer_cacheable(wb) do { (wb)->options |= WB_CONTENT_CACHEABLE; if((wb)->options & WB_CONTENT_NO_CACHEABLE) (wb)->options &= ~WB_CONTENT_NO_CACHEABLE; } while(0)
  77. #define buffer_no_cacheable(wb) do { (wb)->options |= WB_CONTENT_NO_CACHEABLE; if((wb)->options & WB_CONTENT_CACHEABLE) (wb)->options &= ~WB_CONTENT_CACHEABLE; (wb)->expires = 0; } while(0)
  78. #define buffer_strlen(wb) ((wb)->len)
  79. const char *buffer_tostring(BUFFER *wb);
  80. #define BUFFER_OVERFLOW_EOF "EOF"
  81. #ifdef NETDATA_INTERNAL_CHECKS
  82. #define buffer_overflow_check(b) _buffer_overflow_check(b)
  83. #else
  84. #define buffer_overflow_check(b)
  85. #endif
  86. static inline void _buffer_overflow_check(BUFFER *b) {
  87. assert(b->len <= b->size &&
  88. "BUFFER: length is above buffer size.");
  89. assert(!(b->buffer && (b->buffer[b->size] != '\0' || strcmp(&b->buffer[b->size + 1], BUFFER_OVERFLOW_EOF) != 0)) &&
  90. "BUFFER: detected overflow.");
  91. }
  92. static inline void buffer_flush(BUFFER *wb) {
  93. wb->len = 0;
  94. wb->json.depth = 0;
  95. wb->json.stack[0].type = BUFFER_JSON_EMPTY;
  96. wb->json.stack[0].count = 0;
  97. if(wb->buffer)
  98. wb->buffer[0] = '\0';
  99. }
  100. void buffer_reset(BUFFER *wb);
  101. void buffer_date(BUFFER *wb, int year, int month, int day, int hours, int minutes, int seconds);
  102. void buffer_jsdate(BUFFER *wb, int year, int month, int day, int hours, int minutes, int seconds);
  103. BUFFER *buffer_create(size_t size, size_t *statistics);
  104. void buffer_free(BUFFER *b);
  105. void buffer_increase(BUFFER *b, size_t free_size_required);
  106. void buffer_snprintf(BUFFER *wb, size_t len, const char *fmt, ...) PRINTFLIKE(3, 4);
  107. void buffer_vsprintf(BUFFER *wb, const char *fmt, va_list args);
  108. void buffer_sprintf(BUFFER *wb, const char *fmt, ...) PRINTFLIKE(2,3);
  109. void buffer_strcat_htmlescape(BUFFER *wb, const char *txt);
  110. void buffer_char_replace(BUFFER *wb, char from, char to);
  111. void buffer_print_sn_flags(BUFFER *wb, SN_FLAGS flags, bool send_anomaly_bit);
  112. #ifdef ENABLE_H2O
  113. h2o_iovec_t buffer_to_h2o_iovec(BUFFER *wb);
  114. #endif
  115. static inline void buffer_need_bytes(BUFFER *buffer, size_t needed_free_size) {
  116. if(unlikely(buffer->len + needed_free_size >= buffer->size))
  117. buffer_increase(buffer, needed_free_size + 1);
  118. }
  119. void buffer_json_initialize(BUFFER *wb, const char *key_quote, const char *value_quote, int depth,
  120. bool add_anonymous_object, bool minify);
  121. void buffer_json_finalize(BUFFER *wb);
  122. static inline void _buffer_json_depth_push(BUFFER *wb, BUFFER_JSON_NODE_TYPE type) {
  123. #ifdef NETDATA_INTERNAL_CHECKS
  124. assert(wb->json.depth <= BUFFER_JSON_MAX_DEPTH && "BUFFER JSON: max nesting reached");
  125. #endif
  126. wb->json.depth++;
  127. wb->json.stack[wb->json.depth].count = 0;
  128. wb->json.stack[wb->json.depth].type = type;
  129. }
  130. static inline void _buffer_json_depth_pop(BUFFER *wb) {
  131. wb->json.depth--;
  132. }
  133. static inline void buffer_fast_charcat(BUFFER *wb, const char c) {
  134. buffer_need_bytes(wb, 2);
  135. *(&wb->buffer[wb->len]) = c;
  136. wb->len += 1;
  137. wb->buffer[wb->len] = '\0';
  138. buffer_overflow_check(wb);
  139. }
  140. static inline void buffer_fast_rawcat(BUFFER *wb, const char *txt, size_t len) {
  141. if(unlikely(!txt || !*txt || !len)) return;
  142. buffer_need_bytes(wb, len + 1);
  143. const char *t = txt;
  144. const char *e = &txt[len];
  145. char *d = &wb->buffer[wb->len];
  146. while(t != e)
  147. *d++ = *t++;
  148. wb->len += len;
  149. wb->buffer[wb->len] = '\0';
  150. buffer_overflow_check(wb);
  151. }
  152. static inline void buffer_fast_strcat(BUFFER *wb, const char *txt, size_t len) {
  153. if(unlikely(!txt || !*txt || !len)) return;
  154. buffer_need_bytes(wb, len + 1);
  155. const char *t = txt;
  156. const char *e = &txt[len];
  157. char *d = &wb->buffer[wb->len];
  158. while(t != e
  159. #ifdef NETDATA_INTERNAL_CHECKS
  160. && *t
  161. #endif
  162. )
  163. *d++ = *t++;
  164. #ifdef NETDATA_INTERNAL_CHECKS
  165. assert(!(t != e && !*t) && "BUFFER: source string is shorter than the length given.");
  166. #endif
  167. wb->len += len;
  168. wb->buffer[wb->len] = '\0';
  169. buffer_overflow_check(wb);
  170. }
  171. static inline void buffer_strcat(BUFFER *wb, const char *txt) {
  172. if(unlikely(!txt || !*txt)) return;
  173. const char *t = txt;
  174. while(*t) {
  175. buffer_need_bytes(wb, 100);
  176. char *s = &wb->buffer[wb->len];
  177. char *d = s;
  178. const char *e = &wb->buffer[wb->size];
  179. while(*t && d < e)
  180. *d++ = *t++;
  181. wb->len += d - s;
  182. }
  183. buffer_need_bytes(wb, 1);
  184. wb->buffer[wb->len] = '\0';
  185. buffer_overflow_check(wb);
  186. }
  187. static inline void buffer_strncat(BUFFER *wb, const char *txt, size_t len) {
  188. if(unlikely(!txt || !*txt)) return;
  189. const char *t = txt;
  190. buffer_need_bytes(wb, len + 1);
  191. char *s = &wb->buffer[wb->len];
  192. char *d = s;
  193. const char *e = &wb->buffer[wb->len + len];
  194. while(*t && d < e)
  195. *d++ = *t++;
  196. wb->len += d - s;
  197. wb->buffer[wb->len] = '\0';
  198. buffer_overflow_check(wb);
  199. }
  200. static inline void buffer_json_strcat(BUFFER *wb, const char *txt) {
  201. if(unlikely(!txt || !*txt)) return;
  202. const unsigned char *t = (const unsigned char *)txt;
  203. while(*t) {
  204. buffer_need_bytes(wb, 110);
  205. unsigned char *s = (unsigned char *)&wb->buffer[wb->len];
  206. unsigned char *d = s;
  207. const unsigned char *e = (unsigned char *)&wb->buffer[wb->size - 10]; // make room for the max escape sequence
  208. while(*t && d < e) {
  209. #ifdef BUFFER_JSON_ESCAPE_UTF
  210. if(unlikely(IS_UTF8_STARTBYTE(*t) && IS_UTF8_BYTE(t[1]))) {
  211. // UTF-8 multi-byte encoded character
  212. // find how big this character is (2-4 bytes)
  213. size_t utf_character_size = 2;
  214. while(utf_character_size < 4 && t[utf_character_size] && IS_UTF8_BYTE(t[utf_character_size]) && !IS_UTF8_STARTBYTE(t[utf_character_size]))
  215. utf_character_size++;
  216. uint32_t code_point = 0;
  217. for (size_t i = 0; i < utf_character_size; i++) {
  218. code_point <<= 6;
  219. code_point |= (t[i] & 0x3F);
  220. }
  221. t += utf_character_size;
  222. // encode as \u escape sequence
  223. *d++ = '\\';
  224. *d++ = 'u';
  225. *d++ = hex_digits[(code_point >> 12) & 0xf];
  226. *d++ = hex_digits[(code_point >> 8) & 0xf];
  227. *d++ = hex_digits[(code_point >> 4) & 0xf];
  228. *d++ = hex_digits[code_point & 0xf];
  229. }
  230. else
  231. #endif
  232. if(unlikely(*t < ' ')) {
  233. uint32_t v = *t++;
  234. *d++ = '\\';
  235. *d++ = 'u';
  236. *d++ = hex_digits[(v >> 12) & 0xf];
  237. *d++ = hex_digits[(v >> 8) & 0xf];
  238. *d++ = hex_digits[(v >> 4) & 0xf];
  239. *d++ = hex_digits[v & 0xf];
  240. }
  241. else {
  242. if (unlikely(*t == '\\' || *t == '\"'))
  243. *d++ = '\\';
  244. *d++ = *t++;
  245. }
  246. }
  247. wb->len += d - s;
  248. }
  249. buffer_need_bytes(wb, 1);
  250. wb->buffer[wb->len] = '\0';
  251. buffer_overflow_check(wb);
  252. }
  253. static inline void buffer_json_quoted_strcat(BUFFER *wb, const char *txt) {
  254. if(unlikely(!txt || !*txt)) return;
  255. if(*txt == '"')
  256. txt++;
  257. const char *t = txt;
  258. while(*t) {
  259. buffer_need_bytes(wb, 100);
  260. char *s = &wb->buffer[wb->len];
  261. char *d = s;
  262. const char *e = &wb->buffer[wb->size - 1]; // remove 1 to make room for the escape character
  263. while(*t && d < e) {
  264. if(unlikely(*t == '"' && !t[1])) {
  265. t++;
  266. continue;
  267. }
  268. if(unlikely(*t == '\\' || *t == '"'))
  269. *d++ = '\\';
  270. *d++ = *t++;
  271. }
  272. wb->len += d - s;
  273. }
  274. buffer_need_bytes(wb, 1);
  275. wb->buffer[wb->len] = '\0';
  276. buffer_overflow_check(wb);
  277. }
  278. // This trick seems to give an 80% speed increase in 32bit systems
  279. // print_number_llu_r() will just print the digits up to the
  280. // point the remaining value fits in 32 bits, and then calls
  281. // print_number_lu_r() to print the rest with 32 bit arithmetic.
  282. static inline char *print_uint32_reversed(char *dst, uint32_t value) {
  283. char *d = dst;
  284. do *d++ = (char)('0' + (value % 10)); while((value /= 10));
  285. return d;
  286. }
  287. static inline char *print_uint64_reversed(char *dst, uint64_t value) {
  288. #ifdef ENV32BIT
  289. if(value <= (uint64_t)0xffffffff)
  290. return print_uint32_reversed(dst, value);
  291. char *d = dst;
  292. do *d++ = (char)('0' + (value % 10)); while((value /= 10) && value > (uint64_t)0xffffffff);
  293. if(value) return print_uint32_reversed(d, value);
  294. return d;
  295. #else
  296. char *d = dst;
  297. do *d++ = (char)('0' + (value % 10)); while((value /= 10));
  298. return d;
  299. #endif
  300. }
  301. static inline char *print_uint32_hex_reversed(char *dst, uint32_t value) {
  302. static const char *digits = "0123456789ABCDEF";
  303. char *d = dst;
  304. do *d++ = digits[value & 0xf]; while((value >>= 4));
  305. return d;
  306. }
  307. static inline char *print_uint64_hex_reversed(char *dst, uint64_t value) {
  308. #ifdef ENV32BIT
  309. if(value <= (uint64_t)0xffffffff)
  310. return print_uint32_hex_reversed(dst, value);
  311. char *d = dst;
  312. do *d++ = hex_digits[value & 0xf]; while((value >>= 4) && value > (uint64_t)0xffffffff);
  313. if(value) return print_uint32_hex_reversed(d, value);
  314. return d;
  315. #else
  316. char *d = dst;
  317. do *d++ = hex_digits[value & 0xf]; while((value >>= 4));
  318. return d;
  319. #endif
  320. }
  321. static inline char *print_uint64_base64_reversed(char *dst, uint64_t value) {
  322. char *d = dst;
  323. do *d++ = base64_digits[value & 63]; while ((value >>= 6));
  324. return d;
  325. }
  326. static inline void char_array_reverse(char *from, char *to) {
  327. // from and to are inclusive
  328. char *begin = from, *end = to, aux;
  329. while (end > begin) aux = *end, *end-- = *begin, *begin++ = aux;
  330. }
  331. static inline int print_netdata_double(char *dst, NETDATA_DOUBLE value) {
  332. char *s = dst;
  333. if(unlikely(value < 0)) {
  334. *s++ = '-';
  335. value = fabsndd(value);
  336. }
  337. uint64_t fractional_precision = 10000000ULL; // fractional part 7 digits
  338. int fractional_wanted_digits = 7;
  339. int exponent = 0;
  340. if(unlikely(value >= (NETDATA_DOUBLE)(UINT64_MAX / 10))) {
  341. // the number is too big to print using 64bit numbers
  342. // so, let's convert it to exponential notation
  343. exponent = (int)(floorndd(log10ndd(value)));
  344. value /= powndd(10, exponent);
  345. // the max precision we can support is 18 digits
  346. // (UINT64_MAX is 20, but the first is 1)
  347. fractional_precision = 1000000000000000000ULL; // fractional part 18 digits
  348. fractional_wanted_digits = 18;
  349. }
  350. char *d = s;
  351. NETDATA_DOUBLE integral_d, fractional_d;
  352. fractional_d = modfndd(value, &integral_d);
  353. // get the integral and the fractional parts as 64-bit integers
  354. uint64_t integral = (uint64_t)integral_d;
  355. uint64_t fractional = (uint64_t)llrintndd(fractional_d * (NETDATA_DOUBLE)fractional_precision);
  356. if(unlikely(fractional >= fractional_precision)) {
  357. integral++;
  358. fractional -= fractional_precision;
  359. }
  360. // convert the integral part to string (reversed)
  361. d = print_uint64_reversed(d, integral);
  362. char_array_reverse(s, d - 1); // copy reversed the integral string
  363. if(likely(fractional != 0)) {
  364. *d++ = '.'; // add the dot
  365. // convert the fractional part to string (reversed)
  366. d = print_uint64_reversed(s = d, fractional);
  367. while(d - s < fractional_wanted_digits) *d++ = '0'; // prepend zeros to reach precision
  368. char_array_reverse(s, d - 1); // copy reversed the fractional string
  369. // remove trailing zeros from the fractional part
  370. while(*(d - 1) == '0') d--;
  371. }
  372. if(unlikely(exponent != 0)) {
  373. *d++ = 'e';
  374. *d++ = '+';
  375. d = print_uint32_reversed(s = d, exponent);
  376. char_array_reverse(s, d - 1);
  377. }
  378. *d = '\0';
  379. return (int)(d - dst);
  380. }
  381. static inline void buffer_print_uint64(BUFFER *wb, uint64_t value) {
  382. buffer_need_bytes(wb, 50);
  383. char *s = &wb->buffer[wb->len];
  384. char *d = print_uint64_reversed(s, value);
  385. char_array_reverse(s, d - 1);
  386. *d = '\0';
  387. wb->len += d - s;
  388. buffer_overflow_check(wb);
  389. }
  390. static inline void buffer_print_int64(BUFFER *wb, int64_t value) {
  391. buffer_need_bytes(wb, 50);
  392. if(value < 0) {
  393. buffer_fast_strcat(wb, "-", 1);
  394. value = -value;
  395. }
  396. buffer_print_uint64(wb, (uint64_t)value);
  397. buffer_overflow_check(wb);
  398. }
  399. static inline void buffer_print_uint64_hex(BUFFER *wb, uint64_t value) {
  400. buffer_need_bytes(wb, sizeof(uint64_t) * 2 + 2 + 1);
  401. buffer_fast_strcat(wb, HEX_PREFIX, sizeof(HEX_PREFIX) - 1);
  402. char *s = &wb->buffer[wb->len];
  403. char *d = print_uint64_hex_reversed(s, value);
  404. char_array_reverse(s, d - 1);
  405. *d = '\0';
  406. wb->len += d - s;
  407. buffer_overflow_check(wb);
  408. }
  409. static inline void buffer_print_uint64_base64(BUFFER *wb, uint64_t value) {
  410. buffer_need_bytes(wb, sizeof(uint64_t) * 2 + 2 + 1);
  411. buffer_fast_strcat(wb, IEEE754_UINT64_B64_PREFIX, sizeof(IEEE754_UINT64_B64_PREFIX) - 1);
  412. char *s = &wb->buffer[wb->len];
  413. char *d = print_uint64_base64_reversed(s, value);
  414. char_array_reverse(s, d - 1);
  415. *d = '\0';
  416. wb->len += d - s;
  417. buffer_overflow_check(wb);
  418. }
  419. static inline void buffer_print_int64_hex(BUFFER *wb, int64_t value) {
  420. buffer_need_bytes(wb, 2);
  421. if(value < 0) {
  422. buffer_fast_strcat(wb, "-", 1);
  423. value = -value;
  424. }
  425. buffer_print_uint64_hex(wb, (uint64_t)value);
  426. buffer_overflow_check(wb);
  427. }
  428. static inline void buffer_print_int64_base64(BUFFER *wb, int64_t value) {
  429. buffer_need_bytes(wb, 2);
  430. if(value < 0) {
  431. buffer_fast_strcat(wb, "-", 1);
  432. value = -value;
  433. }
  434. buffer_print_uint64_base64(wb, (uint64_t)value);
  435. buffer_overflow_check(wb);
  436. }
  437. static inline void buffer_print_netdata_double(BUFFER *wb, NETDATA_DOUBLE value) {
  438. buffer_need_bytes(wb, 512 + 2);
  439. if(isnan(value) || isinf(value)) {
  440. buffer_fast_strcat(wb, "null", 4);
  441. return;
  442. }
  443. else
  444. wb->len += print_netdata_double(&wb->buffer[wb->len], value);
  445. // terminate it
  446. buffer_need_bytes(wb, 1);
  447. wb->buffer[wb->len] = '\0';
  448. buffer_overflow_check(wb);
  449. }
  450. static inline void buffer_print_netdata_double_hex(BUFFER *wb, NETDATA_DOUBLE value) {
  451. buffer_need_bytes(wb, sizeof(uint64_t) * 2 + 2 + 1 + 1);
  452. uint64_t *ptr = (uint64_t *) (&value);
  453. buffer_fast_strcat(wb, IEEE754_DOUBLE_HEX_PREFIX, sizeof(IEEE754_DOUBLE_HEX_PREFIX) - 1);
  454. char *s = &wb->buffer[wb->len];
  455. char *d = print_uint64_hex_reversed(s, *ptr);
  456. char_array_reverse(s, d - 1);
  457. *d = '\0';
  458. wb->len += d - s;
  459. buffer_overflow_check(wb);
  460. }
  461. static inline void buffer_print_netdata_double_base64(BUFFER *wb, NETDATA_DOUBLE value) {
  462. buffer_need_bytes(wb, sizeof(uint64_t) * 2 + 2 + 1 + 1);
  463. uint64_t *ptr = (uint64_t *) (&value);
  464. buffer_fast_strcat(wb, IEEE754_DOUBLE_B64_PREFIX, sizeof(IEEE754_DOUBLE_B64_PREFIX) - 1);
  465. char *s = &wb->buffer[wb->len];
  466. char *d = print_uint64_base64_reversed(s, *ptr);
  467. char_array_reverse(s, d - 1);
  468. *d = '\0';
  469. wb->len += d - s;
  470. buffer_overflow_check(wb);
  471. }
  472. typedef enum {
  473. NUMBER_ENCODING_DECIMAL,
  474. NUMBER_ENCODING_HEX,
  475. NUMBER_ENCODING_BASE64,
  476. } NUMBER_ENCODING;
  477. static inline void buffer_print_int64_encoded(BUFFER *wb, NUMBER_ENCODING encoding, int64_t value) {
  478. if(encoding == NUMBER_ENCODING_BASE64)
  479. return buffer_print_int64_base64(wb, value);
  480. if(encoding == NUMBER_ENCODING_HEX)
  481. return buffer_print_int64_hex(wb, value);
  482. return buffer_print_int64(wb, value);
  483. }
  484. static inline void buffer_print_uint64_encoded(BUFFER *wb, NUMBER_ENCODING encoding, uint64_t value) {
  485. if(encoding == NUMBER_ENCODING_BASE64)
  486. return buffer_print_uint64_base64(wb, value);
  487. if(encoding == NUMBER_ENCODING_HEX)
  488. return buffer_print_uint64_hex(wb, value);
  489. return buffer_print_uint64(wb, value);
  490. }
  491. static inline void buffer_print_netdata_double_encoded(BUFFER *wb, NUMBER_ENCODING encoding, NETDATA_DOUBLE value) {
  492. if(encoding == NUMBER_ENCODING_BASE64)
  493. return buffer_print_netdata_double_base64(wb, value);
  494. if(encoding == NUMBER_ENCODING_HEX)
  495. return buffer_print_netdata_double_hex(wb, value);
  496. return buffer_print_netdata_double(wb, value);
  497. }
  498. static inline void buffer_print_spaces(BUFFER *wb, size_t spaces) {
  499. buffer_need_bytes(wb, spaces * 4 + 1);
  500. char *d = &wb->buffer[wb->len];
  501. for(size_t i = 0; i < spaces; i++) {
  502. *d++ = ' ';
  503. *d++ = ' ';
  504. *d++ = ' ';
  505. *d++ = ' ';
  506. }
  507. *d = '\0';
  508. wb->len += spaces * 4;
  509. buffer_overflow_check(wb);
  510. }
  511. static inline void buffer_print_json_comma_newline_spacing(BUFFER *wb) {
  512. if(wb->json.stack[wb->json.depth].count)
  513. buffer_fast_strcat(wb, ",", 1);
  514. if(wb->json.minify)
  515. return;
  516. buffer_fast_strcat(wb, "\n", 1);
  517. buffer_print_spaces(wb, wb->json.depth + 1);
  518. }
  519. static inline void buffer_print_json_key(BUFFER *wb, const char *key) {
  520. buffer_strcat(wb, wb->json.key_quote);
  521. buffer_json_strcat(wb, key);
  522. buffer_strcat(wb, wb->json.key_quote);
  523. }
  524. static inline void buffer_json_add_string_value(BUFFER *wb, const char *value) {
  525. if(value) {
  526. buffer_strcat(wb, wb->json.value_quote);
  527. buffer_json_strcat(wb, value);
  528. buffer_strcat(wb, wb->json.value_quote);
  529. }
  530. else
  531. buffer_fast_strcat(wb, "null", 4);
  532. }
  533. static inline void buffer_json_add_quoted_string_value(BUFFER *wb, const char *value) {
  534. if(value) {
  535. buffer_strcat(wb, wb->json.value_quote);
  536. buffer_json_quoted_strcat(wb, value);
  537. buffer_strcat(wb, wb->json.value_quote);
  538. }
  539. else
  540. buffer_fast_strcat(wb, "null", 4);
  541. }
  542. static inline void buffer_json_member_add_object(BUFFER *wb, const char *key) {
  543. buffer_print_json_comma_newline_spacing(wb);
  544. buffer_print_json_key(wb, key);
  545. buffer_fast_strcat(wb, ":{", 2);
  546. wb->json.stack[wb->json.depth].count++;
  547. _buffer_json_depth_push(wb, BUFFER_JSON_OBJECT);
  548. }
  549. static inline void buffer_json_object_close(BUFFER *wb) {
  550. #ifdef NETDATA_INTERNAL_CHECKS
  551. assert(wb->json.depth >= 0 && "BUFFER JSON: nothing is open to close it");
  552. assert(wb->json.stack[wb->json.depth].type == BUFFER_JSON_OBJECT && "BUFFER JSON: an object is not open to close it");
  553. #endif
  554. if(!wb->json.minify) {
  555. buffer_fast_strcat(wb, "\n", 1);
  556. buffer_print_spaces(wb, wb->json.depth);
  557. }
  558. buffer_fast_strcat(wb, "}", 1);
  559. _buffer_json_depth_pop(wb);
  560. }
  561. static inline void buffer_json_member_add_string(BUFFER *wb, const char *key, const char *value) {
  562. buffer_print_json_comma_newline_spacing(wb);
  563. buffer_print_json_key(wb, key);
  564. buffer_fast_strcat(wb, ":", 1);
  565. buffer_json_add_string_value(wb, value);
  566. wb->json.stack[wb->json.depth].count++;
  567. }
  568. static inline void buffer_json_member_add_string_or_omit(BUFFER *wb, const char *key, const char *value) {
  569. if(value && *value)
  570. buffer_json_member_add_string(wb, key, value);
  571. }
  572. static inline void buffer_json_member_add_string_or_empty(BUFFER *wb, const char *key, const char *value) {
  573. if(!value)
  574. value = "";
  575. buffer_json_member_add_string(wb, key, value);
  576. }
  577. static inline void buffer_json_member_add_quoted_string(BUFFER *wb, const char *key, const char *value) {
  578. buffer_print_json_comma_newline_spacing(wb);
  579. buffer_print_json_key(wb, key);
  580. buffer_fast_strcat(wb, ":", 1);
  581. if(!value || strcmp(value, "null") == 0)
  582. buffer_fast_strcat(wb, "null", 4);
  583. else
  584. buffer_json_add_quoted_string_value(wb, value);
  585. wb->json.stack[wb->json.depth].count++;
  586. }
  587. static inline void buffer_json_member_add_uuid(BUFFER *wb, const char *key, uuid_t *value) {
  588. buffer_print_json_comma_newline_spacing(wb);
  589. buffer_print_json_key(wb, key);
  590. buffer_fast_strcat(wb, ":", 1);
  591. if(value && !uuid_is_null(*value)) {
  592. char uuid[GUID_LEN + 1];
  593. uuid_unparse_lower(*value, uuid);
  594. buffer_json_add_string_value(wb, uuid);
  595. }
  596. else
  597. buffer_json_add_string_value(wb, NULL);
  598. wb->json.stack[wb->json.depth].count++;
  599. }
  600. static inline void buffer_json_member_add_boolean(BUFFER *wb, const char *key, bool value) {
  601. buffer_print_json_comma_newline_spacing(wb);
  602. buffer_print_json_key(wb, key);
  603. buffer_fast_strcat(wb, ":", 1);
  604. buffer_strcat(wb, value?"true":"false");
  605. wb->json.stack[wb->json.depth].count++;
  606. }
  607. static inline void buffer_json_member_add_array(BUFFER *wb, const char *key) {
  608. buffer_print_json_comma_newline_spacing(wb);
  609. buffer_print_json_key(wb, key);
  610. buffer_fast_strcat(wb, ":[", 2);
  611. wb->json.stack[wb->json.depth].count++;
  612. _buffer_json_depth_push(wb, BUFFER_JSON_ARRAY);
  613. }
  614. static inline void buffer_json_add_array_item_array(BUFFER *wb) {
  615. buffer_print_json_comma_newline_spacing(wb);
  616. buffer_fast_strcat(wb, "[", 1);
  617. wb->json.stack[wb->json.depth].count++;
  618. _buffer_json_depth_push(wb, BUFFER_JSON_ARRAY);
  619. }
  620. static inline void buffer_json_add_array_item_string(BUFFER *wb, const char *value) {
  621. if(wb->json.stack[wb->json.depth].count)
  622. buffer_fast_strcat(wb, ",", 1);
  623. buffer_json_add_string_value(wb, value);
  624. wb->json.stack[wb->json.depth].count++;
  625. }
  626. static inline void buffer_json_add_array_item_double(BUFFER *wb, NETDATA_DOUBLE value) {
  627. if(wb->json.stack[wb->json.depth].count)
  628. buffer_fast_strcat(wb, ",", 1);
  629. buffer_print_netdata_double(wb, value);
  630. wb->json.stack[wb->json.depth].count++;
  631. }
  632. static inline void buffer_json_add_array_item_int64(BUFFER *wb, int64_t value) {
  633. if(wb->json.stack[wb->json.depth].count)
  634. buffer_fast_strcat(wb, ",", 1);
  635. buffer_print_int64(wb, value);
  636. wb->json.stack[wb->json.depth].count++;
  637. }
  638. static inline void buffer_json_add_array_item_uint64(BUFFER *wb, uint64_t value) {
  639. if(wb->json.stack[wb->json.depth].count)
  640. buffer_fast_strcat(wb, ",", 1);
  641. buffer_print_uint64(wb, value);
  642. wb->json.stack[wb->json.depth].count++;
  643. }
  644. static inline void buffer_json_add_array_item_time_t(BUFFER *wb, time_t value) {
  645. if(wb->json.stack[wb->json.depth].count)
  646. buffer_fast_strcat(wb, ",", 1);
  647. buffer_print_int64(wb, value);
  648. wb->json.stack[wb->json.depth].count++;
  649. }
  650. static inline void buffer_json_add_array_item_time_ms(BUFFER *wb, time_t value) {
  651. if(wb->json.stack[wb->json.depth].count)
  652. buffer_fast_strcat(wb, ",", 1);
  653. buffer_print_int64(wb, value);
  654. buffer_fast_strcat(wb, "000", 3);
  655. wb->json.stack[wb->json.depth].count++;
  656. }
  657. static inline void buffer_json_add_array_item_time_t2ms(BUFFER *wb, time_t value) {
  658. if(wb->json.stack[wb->json.depth].count)
  659. buffer_fast_strcat(wb, ",", 1);
  660. buffer_print_int64(wb, value);
  661. buffer_fast_strcat(wb, "000", 3);
  662. wb->json.stack[wb->json.depth].count++;
  663. }
  664. static inline void buffer_json_add_array_item_object(BUFFER *wb) {
  665. if(wb->json.stack[wb->json.depth].count)
  666. buffer_fast_strcat(wb, ",", 1);
  667. buffer_fast_strcat(wb, "{", 1);
  668. wb->json.stack[wb->json.depth].count++;
  669. _buffer_json_depth_push(wb, BUFFER_JSON_OBJECT);
  670. }
  671. static inline void buffer_json_member_add_time_t(BUFFER *wb, const char *key, time_t value) {
  672. buffer_print_json_comma_newline_spacing(wb);
  673. buffer_print_json_key(wb, key);
  674. buffer_fast_strcat(wb, ":", 1);
  675. buffer_print_int64(wb, value);
  676. wb->json.stack[wb->json.depth].count++;
  677. }
  678. static inline void buffer_json_member_add_time_t2ms(BUFFER *wb, const char *key, time_t value) {
  679. buffer_print_json_comma_newline_spacing(wb);
  680. buffer_print_json_key(wb, key);
  681. buffer_fast_strcat(wb, ":", 1);
  682. buffer_print_int64(wb, value);
  683. buffer_fast_strcat(wb, "000", 3);
  684. wb->json.stack[wb->json.depth].count++;
  685. }
  686. static inline void buffer_json_member_add_uint64(BUFFER *wb, const char *key, uint64_t value) {
  687. buffer_print_json_comma_newline_spacing(wb);
  688. buffer_print_json_key(wb, key);
  689. buffer_fast_strcat(wb, ":", 1);
  690. buffer_print_uint64(wb, value);
  691. wb->json.stack[wb->json.depth].count++;
  692. }
  693. static inline void buffer_json_member_add_int64(BUFFER *wb, const char *key, int64_t value) {
  694. buffer_print_json_comma_newline_spacing(wb);
  695. buffer_print_json_key(wb, key);
  696. buffer_fast_strcat(wb, ":", 1);
  697. buffer_print_int64(wb, value);
  698. wb->json.stack[wb->json.depth].count++;
  699. }
  700. static inline void buffer_json_member_add_double(BUFFER *wb, const char *key, NETDATA_DOUBLE value) {
  701. buffer_print_json_comma_newline_spacing(wb);
  702. buffer_print_json_key(wb, key);
  703. buffer_fast_strcat(wb, ":", 1);
  704. buffer_print_netdata_double(wb, value);
  705. wb->json.stack[wb->json.depth].count++;
  706. }
  707. static inline void buffer_json_array_close(BUFFER *wb) {
  708. #ifdef NETDATA_INTERNAL_CHECKS
  709. assert(wb->json.depth >= 0 && "BUFFER JSON: nothing is open to close it");
  710. assert(wb->json.stack[wb->json.depth].type == BUFFER_JSON_ARRAY && "BUFFER JSON: an array is not open to close it");
  711. #endif
  712. buffer_fast_strcat(wb, "]", 1);
  713. _buffer_json_depth_pop(wb);
  714. }
  715. typedef enum __attribute__((packed)) {
  716. RRDF_FIELD_OPTS_NONE = 0,
  717. RRDF_FIELD_OPTS_UNIQUE_KEY = (1 << 0), // the field is the unique key of the row
  718. RRDF_FIELD_OPTS_VISIBLE = (1 << 1), // the field should be visible by default
  719. RRDF_FIELD_OPTS_STICKY = (1 << 2), // the field should be sticky
  720. } RRDF_FIELD_OPTIONS;
  721. typedef enum __attribute__((packed)) {
  722. RRDF_FIELD_TYPE_INTEGER,
  723. RRDF_FIELD_TYPE_STRING,
  724. RRDF_FIELD_TYPE_DETAIL_STRING,
  725. RRDF_FIELD_TYPE_BAR_WITH_INTEGER,
  726. RRDF_FIELD_TYPE_DURATION,
  727. RRDF_FIELD_TYPE_TIMESTAMP,
  728. RRDF_FIELD_TYPE_ARRAY,
  729. } RRDF_FIELD_TYPE;
  730. static inline const char *rrdf_field_type_to_string(RRDF_FIELD_TYPE type) {
  731. switch(type) {
  732. default:
  733. case RRDF_FIELD_TYPE_INTEGER:
  734. return "integer";
  735. case RRDF_FIELD_TYPE_STRING:
  736. return "string";
  737. case RRDF_FIELD_TYPE_DETAIL_STRING:
  738. return "detail-string";
  739. case RRDF_FIELD_TYPE_BAR_WITH_INTEGER:
  740. return "bar-with-integer";
  741. case RRDF_FIELD_TYPE_DURATION:
  742. return "duration";
  743. case RRDF_FIELD_TYPE_TIMESTAMP:
  744. return "timestamp";
  745. case RRDF_FIELD_TYPE_ARRAY:
  746. return "array";
  747. }
  748. }
  749. typedef enum __attribute__((packed)) {
  750. RRDF_FIELD_VISUAL_VALUE, // show the value, possibly applying a transformation
  751. RRDF_FIELD_VISUAL_BAR, // show the value and a bar, respecting the max field to fill the bar at 100%
  752. RRDF_FIELD_VISUAL_PILL, // array of values (transformation is respected)
  753. } RRDF_FIELD_VISUAL;
  754. static inline const char *rrdf_field_visual_to_string(RRDF_FIELD_VISUAL visual) {
  755. switch(visual) {
  756. default:
  757. case RRDF_FIELD_VISUAL_VALUE:
  758. return "value";
  759. case RRDF_FIELD_VISUAL_BAR:
  760. return "bar";
  761. case RRDF_FIELD_VISUAL_PILL:
  762. return "pill";
  763. }
  764. }
  765. typedef enum __attribute__((packed)) {
  766. RRDF_FIELD_TRANSFORM_NONE, // show the value as-is
  767. RRDF_FIELD_TRANSFORM_NUMBER, // show the value repsecting the decimal_points
  768. RRDF_FIELD_TRANSFORM_DURATION, // transform as duration in second to a human readable duration
  769. RRDF_FIELD_TRANSFORM_DATETIME, // UNIX epoch timestamp in ms
  770. } RRDF_FIELD_TRANSFORM;
  771. static inline const char *rrdf_field_transform_to_string(RRDF_FIELD_TRANSFORM transform) {
  772. switch(transform) {
  773. default:
  774. case RRDF_FIELD_TRANSFORM_NONE:
  775. return "none";
  776. case RRDF_FIELD_TRANSFORM_NUMBER:
  777. return "number";
  778. case RRDF_FIELD_TRANSFORM_DURATION:
  779. return "duration";
  780. case RRDF_FIELD_TRANSFORM_DATETIME:
  781. return "datetime";
  782. }
  783. }
  784. typedef enum __attribute__((packed)) {
  785. RRDF_FIELD_SORT_ASCENDING = (1 << 0),
  786. RRDF_FIELD_SORT_DESCENDING = (1 << 1),
  787. RRDF_FIELD_SORT_FIXED = (1 << 7),
  788. } RRDF_FIELD_SORT;
  789. static inline const char *rrdf_field_sort_to_string(RRDF_FIELD_SORT sort) {
  790. if(sort & RRDF_FIELD_SORT_DESCENDING)
  791. return "descending";
  792. else
  793. return "ascending";
  794. }
  795. typedef enum __attribute__((packed)) {
  796. RRDF_FIELD_SUMMARY_UNIQUECOUNT, // Finds the number of unique values of a group of rows
  797. RRDF_FIELD_SUMMARY_SUM, // Sums the values of a group of rows
  798. RRDF_FIELD_SUMMARY_MIN, // Finds the minimum value of a group of rows
  799. RRDF_FIELD_SUMMARY_MAX, // Finds the maximum value of a group of rows
  800. // RRDF_FIELD_SUMMARY_EXTENT, // Finds the minimum and maximum values of a group of rows
  801. RRDF_FIELD_SUMMARY_MEAN, // Finds the mean/average value of a group of rows
  802. RRDF_FIELD_SUMMARY_MEDIAN, // Finds the median value of a group of rows
  803. // RRDF_FIELD_SUMMARY_UNIQUE, // Finds the unique values of a group of rows
  804. RRDF_FIELD_SUMMARY_COUNT, // Calculates the number of rows in a group
  805. } RRDF_FIELD_SUMMARY;
  806. static inline const char *rrdf_field_summary_to_string(RRDF_FIELD_SUMMARY summary) {
  807. switch(summary) {
  808. default:
  809. case RRDF_FIELD_SUMMARY_COUNT:
  810. return "count";
  811. case RRDF_FIELD_SUMMARY_UNIQUECOUNT:
  812. return "uniqueCount";
  813. case RRDF_FIELD_SUMMARY_SUM:
  814. return "sum";
  815. case RRDF_FIELD_SUMMARY_MIN:
  816. return "min";
  817. case RRDF_FIELD_SUMMARY_MEAN:
  818. return "mean";
  819. case RRDF_FIELD_SUMMARY_MEDIAN:
  820. return "median";
  821. case RRDF_FIELD_SUMMARY_MAX:
  822. return "max";
  823. }
  824. }
  825. typedef enum __attribute__((packed)) {
  826. RRDF_FIELD_FILTER_RANGE,
  827. RRDF_FIELD_FILTER_MULTISELECT,
  828. } RRDF_FIELD_FILTER;
  829. static inline const char *rrdf_field_filter_to_string(RRDF_FIELD_FILTER filter) {
  830. switch(filter) {
  831. default:
  832. case RRDF_FIELD_FILTER_RANGE:
  833. return "range";
  834. case RRDF_FIELD_FILTER_MULTISELECT:
  835. return "multiselect";
  836. }
  837. }
  838. static inline void
  839. buffer_rrdf_table_add_field(BUFFER *wb, size_t field_id, const char *key, const char *name, RRDF_FIELD_TYPE type,
  840. RRDF_FIELD_VISUAL visual, RRDF_FIELD_TRANSFORM transform, size_t decimal_points,
  841. const char *units, NETDATA_DOUBLE max, RRDF_FIELD_SORT sort, const char *pointer_to,
  842. RRDF_FIELD_SUMMARY summary, RRDF_FIELD_FILTER filter, RRDF_FIELD_OPTIONS options,
  843. const char *default_value) {
  844. buffer_json_member_add_object(wb, key);
  845. {
  846. buffer_json_member_add_uint64(wb, "index", field_id);
  847. buffer_json_member_add_boolean(wb, "unique_key", options & RRDF_FIELD_OPTS_UNIQUE_KEY);
  848. buffer_json_member_add_string(wb, "name", name);
  849. buffer_json_member_add_boolean(wb, "visible", options & RRDF_FIELD_OPTS_VISIBLE);
  850. buffer_json_member_add_string(wb, "type", rrdf_field_type_to_string(type));
  851. buffer_json_member_add_string_or_omit(wb, "units", units);
  852. buffer_json_member_add_string(wb, "visualization", rrdf_field_visual_to_string(visual));
  853. buffer_json_member_add_object(wb, "value_options");
  854. {
  855. buffer_json_member_add_string_or_omit(wb, "units", units);
  856. buffer_json_member_add_string(wb, "transform", rrdf_field_transform_to_string(transform));
  857. buffer_json_member_add_uint64(wb, "decimal_points", decimal_points);
  858. buffer_json_member_add_string(wb, "default_value", default_value);
  859. }
  860. buffer_json_object_close(wb);
  861. if (!isnan((NETDATA_DOUBLE) (max)))
  862. buffer_json_member_add_double(wb, "max", (NETDATA_DOUBLE) (max));
  863. buffer_json_member_add_string_or_omit(wb, "pointer_to", pointer_to);
  864. buffer_json_member_add_string(wb, "sort", rrdf_field_sort_to_string(sort));
  865. buffer_json_member_add_boolean(wb, "sortable", !(sort & RRDF_FIELD_SORT_FIXED));
  866. buffer_json_member_add_boolean(wb, "sticky", options & RRDF_FIELD_OPTS_STICKY);
  867. buffer_json_member_add_string(wb, "summary", rrdf_field_summary_to_string(summary));
  868. buffer_json_member_add_string(wb, "filter", rrdf_field_filter_to_string(filter));
  869. }
  870. buffer_json_object_close(wb);
  871. }
  872. #endif /* NETDATA_WEB_BUFFER_H */