inlined.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #ifndef NETDATA_INLINED_H
  3. #define NETDATA_INLINED_H 1
  4. #include "libnetdata.h"
  5. #ifdef KERNEL_32BIT
  6. typedef uint32_t kernel_uint_t;
  7. #define str2kernel_uint_t(string) str2uint32_t(string, NULL)
  8. #define KERNEL_UINT_FORMAT "%u"
  9. #else
  10. typedef uint64_t kernel_uint_t;
  11. #define str2kernel_uint_t(string) str2uint64_t(string, NULL)
  12. #define KERNEL_UINT_FORMAT "%" PRIu64
  13. #endif
  14. #define str2pid_t(string) str2uint32_t(string, NULL)
  15. // for faster execution, allow the compiler to inline
  16. // these functions that are called thousands of times per second
  17. static inline uint32_t djb2_hash32(const char* name) {
  18. unsigned char *s = (unsigned char *) name;
  19. uint32_t hash = 5381;
  20. while (*s)
  21. hash = ((hash << 5) + hash) + (uint32_t) *s++; // hash * 33 + char
  22. return hash;
  23. }
  24. static inline uint32_t pluginsd_parser_hash32(const char *name) {
  25. unsigned char *s = (unsigned char *) name;
  26. uint32_t hash = 0;
  27. while (*s) {
  28. hash <<= 5;
  29. hash += *s++ - ' ';
  30. }
  31. return hash;
  32. }
  33. // https://stackoverflow.com/a/107657
  34. static inline uint32_t larson_hash32(const char *name) {
  35. unsigned char *s = (unsigned char *) name;
  36. uint32_t hash = 0;
  37. while (*s)
  38. hash = hash * 101 + (uint32_t) *s++;
  39. return hash;
  40. }
  41. // http://isthe.com/chongo/tech/comp/fnv/
  42. static inline uint32_t fnv1_hash32(const char *name) {
  43. unsigned char *s = (unsigned char *) name;
  44. uint32_t hash = 0x811c9dc5;
  45. while (*s) {
  46. hash *= 0x01000193; // 16777619
  47. hash ^= (uint32_t) *s++;
  48. }
  49. return hash;
  50. }
  51. // http://isthe.com/chongo/tech/comp/fnv/
  52. static inline uint32_t fnv1a_hash32(const char *name) {
  53. unsigned char *s = (unsigned char *) name;
  54. uint32_t hash = 0x811c9dc5;
  55. while (*s) {
  56. hash ^= (uint32_t) *s++;
  57. hash *= 0x01000193; // 16777619
  58. }
  59. return hash;
  60. }
  61. static inline uint32_t fnv1a_uhash32(const char *name) {
  62. unsigned char *s = (unsigned char *) name;
  63. uint32_t hash = 0x811c9dc5, c;
  64. while ((c = *s++)) {
  65. if (unlikely(c >= 'A' && c <= 'Z')) c += 'a' - 'A';
  66. hash ^= c;
  67. hash *= 0x01000193; // 16777619
  68. }
  69. return hash;
  70. }
  71. #define simple_hash(s) fnv1a_hash32(s)
  72. #define simple_uhash(s) fnv1a_uhash32(s)
  73. static uint32_t murmur32(uint32_t k) __attribute__((const));
  74. static inline uint32_t murmur32(uint32_t k) {
  75. k ^= k >> 16;
  76. k *= 0x85ebca6b;
  77. k ^= k >> 13;
  78. k *= 0xc2b2ae35;
  79. k ^= k >> 16;
  80. return k;
  81. }
  82. static uint64_t murmur64(uint64_t k) __attribute__((const));
  83. static inline uint64_t murmur64(uint64_t k) {
  84. k ^= k >> 33;
  85. k *= 0xff51afd7ed558ccdUL;
  86. k ^= k >> 33;
  87. k *= 0xc4ceb9fe1a85ec53UL;
  88. k ^= k >> 33;
  89. return k;
  90. }
  91. static inline size_t indexing_partition(Word_t ptr, Word_t modulo) __attribute__((const));
  92. static inline size_t indexing_partition(Word_t ptr, Word_t modulo) {
  93. #ifdef ENV64BIT
  94. uint64_t hash = murmur64(ptr);
  95. return hash % modulo;
  96. #else
  97. uint32_t hash = murmur32(ptr);
  98. return hash % modulo;
  99. #endif
  100. }
  101. static inline unsigned int str2u(const char *s) {
  102. unsigned int n = 0;
  103. while(*s >= '0' && *s <= '9')
  104. n = n * 10 + (*s++ - '0');
  105. return n;
  106. }
  107. static inline int str2i(const char *s) {
  108. if(unlikely(*s == '-')) {
  109. s++;
  110. return -(int) str2u(s);
  111. }
  112. else {
  113. if(unlikely(*s == '+')) s++;
  114. return (int) str2u(s);
  115. }
  116. }
  117. static inline unsigned long str2ul(const char *s) {
  118. unsigned long n = 0;
  119. while(*s >= '0' && *s <= '9')
  120. n = n * 10 + (*s++ - '0');
  121. return n;
  122. }
  123. static inline long str2l(const char *s) {
  124. if(unlikely(*s == '-')) {
  125. s++;
  126. return -(long) str2ul(s);
  127. }
  128. else {
  129. if(unlikely(*s == '+')) s++;
  130. return (long) str2ul(s);
  131. }
  132. }
  133. static inline uint32_t str2uint32_t(const char *s, char **endptr) {
  134. uint32_t n = 0;
  135. while(*s >= '0' && *s <= '9')
  136. n = n * 10 + (*s++ - '0');
  137. if(unlikely(endptr))
  138. *endptr = (char *)s;
  139. return n;
  140. }
  141. static inline uint64_t str2uint64_t(const char *s, char **endptr) {
  142. uint64_t n = 0;
  143. #ifdef ENV32BIT
  144. unsigned long n32 = 0;
  145. while (*s >= '0' && *s <= '9' && n32 < (ULONG_MAX / 10))
  146. n32 = n32 * 10 + (*s++ - '0');
  147. n = n32;
  148. #endif
  149. while(*s >= '0' && *s <= '9')
  150. n = n * 10 + (*s++ - '0');
  151. if(unlikely(endptr))
  152. *endptr = (char *)s;
  153. return n;
  154. }
  155. static inline unsigned long long int str2ull(const char *s, char **endptr) {
  156. return str2uint64_t(s, endptr);
  157. }
  158. static inline long long str2ll(const char *s, char **endptr) {
  159. if(unlikely(*s == '-')) {
  160. s++;
  161. return -(long long) str2uint64_t(s, endptr);
  162. }
  163. else {
  164. if(unlikely(*s == '+')) s++;
  165. return (long long) str2uint64_t(s, endptr);
  166. }
  167. }
  168. static inline uint64_t str2uint64_hex(const char *src, char **endptr) {
  169. uint64_t num = 0;
  170. const unsigned char *s = (const unsigned char *)src;
  171. unsigned char c;
  172. while ((c = hex_value_from_ascii[toupper(*s)]) != 255) {
  173. num = (num << 4) | c;
  174. s++;
  175. }
  176. if(endptr)
  177. *endptr = (char *)s;
  178. return num;
  179. }
  180. static inline uint64_t str2uint64_base64(const char *src, char **endptr) {
  181. uint64_t num = 0;
  182. const unsigned char *s = (const unsigned char *)src;
  183. unsigned char c;
  184. while ((c = base64_value_from_ascii[*s]) != 255) {
  185. num = (num << 6) | c;
  186. s++;
  187. }
  188. if(endptr)
  189. *endptr = (char *)s;
  190. return num;
  191. }
  192. static inline NETDATA_DOUBLE str2ndd_parse_double_decimal_digits_internal(const char *src, int *digits) {
  193. const char *s = src;
  194. NETDATA_DOUBLE n = 0.0;
  195. while(*s >= '0' && *s <= '9') {
  196. // this works for both 32-bit and 64-bit systems
  197. unsigned long ni = 0;
  198. unsigned exponent = 0;
  199. while (*s >= '0' && *s <= '9' && ni < (ULONG_MAX / 10)) {
  200. ni = (ni * 10) + (*s++ - '0');
  201. exponent++;
  202. }
  203. n = n * powndd(10.0, exponent) + (NETDATA_DOUBLE)ni;
  204. }
  205. *digits = (int)(s - src);
  206. return n;
  207. }
  208. static inline NETDATA_DOUBLE str2ndd(const char *src, char **endptr) {
  209. const char *s = src;
  210. NETDATA_DOUBLE sign = 1.0;
  211. NETDATA_DOUBLE result;
  212. int integral_digits = 0;
  213. NETDATA_DOUBLE fractional = 0.0;
  214. int fractional_digits = 0;
  215. NETDATA_DOUBLE exponent = 0.0;
  216. int exponent_digits = 0;
  217. switch(*s) {
  218. case '-':
  219. s++;
  220. sign = -1.0;
  221. break;
  222. case '+':
  223. s++;
  224. break;
  225. case 'n':
  226. if(s[1] == 'a' && s[2] == 'n') {
  227. if(endptr) *endptr = (char *)&s[3];
  228. return NAN;
  229. }
  230. if(s[1] == 'u' && s[2] == 'l' && s[3] == 'l') {
  231. if(endptr) *endptr = (char *)&s[3];
  232. return NAN;
  233. }
  234. break;
  235. case 'i':
  236. if(s[1] == 'n' && s[2] == 'f') {
  237. if(endptr) *endptr = (char *)&s[3];
  238. return INFINITY;
  239. }
  240. break;
  241. default:
  242. break;
  243. }
  244. result = str2ndd_parse_double_decimal_digits_internal(s, &integral_digits);
  245. s += integral_digits;
  246. if(unlikely(*s == '.')) {
  247. s++;
  248. fractional = str2ndd_parse_double_decimal_digits_internal(s, &fractional_digits);
  249. s += fractional_digits;
  250. }
  251. if (unlikely(*s == 'e' || *s == 'E')) {
  252. const char *e_ptr = s;
  253. s++;
  254. int exponent_sign = 1;
  255. if (*s == '-') {
  256. exponent_sign = -1;
  257. s++;
  258. }
  259. else if(*s == '+')
  260. s++;
  261. exponent = str2ndd_parse_double_decimal_digits_internal(s, &exponent_digits);
  262. if(unlikely(!exponent_digits)) {
  263. exponent = 0;
  264. s = e_ptr;
  265. }
  266. else {
  267. s += exponent_digits;
  268. exponent *= exponent_sign;
  269. }
  270. }
  271. if(unlikely(endptr))
  272. *endptr = (char *)s;
  273. if (unlikely(exponent_digits))
  274. result *= powndd(10.0, exponent);
  275. if (unlikely(fractional_digits))
  276. result += fractional / powndd(10.0, fractional_digits) * (exponent_digits ? powndd(10.0, exponent) : 1.0);
  277. return sign * result;
  278. }
  279. static inline unsigned long long str2ull_encoded(const char *s) {
  280. if(*s == IEEE754_UINT64_B64_PREFIX[0])
  281. return str2uint64_base64(s + sizeof(IEEE754_UINT64_B64_PREFIX) - 1, NULL);
  282. if(s[0] == HEX_PREFIX[0] && s[1] == HEX_PREFIX[1])
  283. return str2uint64_hex(s + 2, NULL);
  284. return str2uint64_t(s, NULL);
  285. }
  286. static inline long long str2ll_encoded(const char *s) {
  287. if(*s == '-')
  288. return -(long long) str2ull_encoded(&s[1]);
  289. else
  290. return (long long) str2ull_encoded(s);
  291. }
  292. static inline NETDATA_DOUBLE str2ndd_encoded(const char *src, char **endptr) {
  293. if (*src == IEEE754_DOUBLE_B64_PREFIX[0]) {
  294. // double parsing from base64
  295. uint64_t n = str2uint64_base64(src + sizeof(IEEE754_DOUBLE_B64_PREFIX) - 1, endptr);
  296. NETDATA_DOUBLE *ptr = (NETDATA_DOUBLE *) (&n);
  297. return *ptr;
  298. }
  299. if (*src == IEEE754_DOUBLE_HEX_PREFIX[0]) {
  300. // double parsing from hex
  301. uint64_t n = str2uint64_hex(src + sizeof(IEEE754_DOUBLE_HEX_PREFIX) - 1, endptr);
  302. NETDATA_DOUBLE *ptr = (NETDATA_DOUBLE *) (&n);
  303. return *ptr;
  304. }
  305. double sign = 1.0;
  306. if(*src == '-') {
  307. sign = -1.0;
  308. src++;
  309. }
  310. if(unlikely(*src == IEEE754_UINT64_B64_PREFIX[0]))
  311. return (NETDATA_DOUBLE) str2uint64_base64(src + sizeof(IEEE754_UINT64_B64_PREFIX) - 1, endptr) * sign;
  312. if(unlikely(*src == HEX_PREFIX[0] && src[1] == HEX_PREFIX[1]))
  313. return (NETDATA_DOUBLE) str2uint64_hex(src + sizeof(HEX_PREFIX) - 1, endptr) * sign;
  314. return str2ndd(src, endptr) * sign;
  315. }
  316. static inline char *strncpyz(char *dst, const char *src, size_t n) {
  317. char *p = dst;
  318. while (*src && n--)
  319. *dst++ = *src++;
  320. *dst = '\0';
  321. return p;
  322. }
  323. static inline void sanitize_json_string(char *dst, const char *src, size_t dst_size) {
  324. while (*src != '\0' && dst_size > 1) {
  325. if (*src < 0x1F) {
  326. *dst++ = '_';
  327. src++;
  328. dst_size--;
  329. }
  330. else if (*src == '\\' || *src == '\"') {
  331. *dst++ = '\\';
  332. *dst++ = *src++;
  333. dst_size -= 2;
  334. }
  335. else {
  336. *dst++ = *src++;
  337. dst_size--;
  338. }
  339. }
  340. *dst = '\0';
  341. }
  342. static inline bool sanitize_command_argument_string(char *dst, const char *src, size_t dst_size) {
  343. // skip leading dashes
  344. while (src[0] == '-')
  345. src++;
  346. // escape single quotes
  347. while (src[0] != '\0') {
  348. if (src[0] == '\'') {
  349. if (dst_size < 4)
  350. return false;
  351. dst[0] = '\''; dst[1] = '\\'; dst[2] = '\''; dst[3] = '\'';
  352. dst += 4;
  353. dst_size -= 4;
  354. } else {
  355. if (dst_size < 1)
  356. return false;
  357. dst[0] = src[0];
  358. dst += 1;
  359. dst_size -= 1;
  360. }
  361. src++;
  362. }
  363. // make sure we have space to terminate the string
  364. if (dst_size == 0)
  365. return false;
  366. *dst = '\0';
  367. return true;
  368. }
  369. static inline int read_file(const char *filename, char *buffer, size_t size) {
  370. if(unlikely(!size)) return 3;
  371. int fd = open(filename, O_RDONLY, 0666);
  372. if(unlikely(fd == -1)) {
  373. buffer[0] = '\0';
  374. return 1;
  375. }
  376. ssize_t r = read(fd, buffer, size);
  377. if(unlikely(r == -1)) {
  378. buffer[0] = '\0';
  379. close(fd);
  380. return 2;
  381. }
  382. buffer[r] = '\0';
  383. close(fd);
  384. return 0;
  385. }
  386. static inline int read_single_number_file(const char *filename, unsigned long long *result) {
  387. char buffer[30 + 1];
  388. int ret = read_file(filename, buffer, 30);
  389. if(unlikely(ret)) {
  390. *result = 0;
  391. return ret;
  392. }
  393. buffer[30] = '\0';
  394. *result = str2ull(buffer, NULL);
  395. return 0;
  396. }
  397. static inline int read_single_signed_number_file(const char *filename, long long *result) {
  398. char buffer[30 + 1];
  399. int ret = read_file(filename, buffer, 30);
  400. if(unlikely(ret)) {
  401. *result = 0;
  402. return ret;
  403. }
  404. buffer[30] = '\0';
  405. *result = atoll(buffer);
  406. return 0;
  407. }
  408. static inline int read_single_base64_or_hex_number_file(const char *filename, unsigned long long *result) {
  409. char buffer[30 + 1];
  410. int ret = read_file(filename, buffer, 30);
  411. if(unlikely(ret)) {
  412. *result = 0;
  413. return ret;
  414. }
  415. buffer[30] = '\0';
  416. if(likely(buffer[0])){
  417. *result = str2ull_encoded(buffer);
  418. return 0;
  419. }
  420. else {
  421. *result = 0;
  422. return -1;
  423. }
  424. }
  425. static inline int uuid_memcmp(const uuid_t *uu1, const uuid_t *uu2) {
  426. return memcmp(uu1, uu2, sizeof(uuid_t));
  427. }
  428. static inline char *strsep_skip_consecutive_separators(char **ptr, char *s) {
  429. char *p = (char *)"";
  430. while (p && !p[0] && *ptr) p = strsep(ptr, s);
  431. return (p);
  432. }
  433. // remove leading and trailing spaces; may return NULL
  434. static inline char *trim(char *s) {
  435. // skip leading spaces
  436. while (*s && isspace(*s)) s++;
  437. if (!*s) return NULL;
  438. // skip tailing spaces
  439. // this way is way faster. Writes only one NUL char.
  440. ssize_t l = (ssize_t)strlen(s);
  441. if (--l >= 0) {
  442. char *p = s + l;
  443. while (p > s && isspace(*p)) p--;
  444. *++p = '\0';
  445. }
  446. if (!*s) return NULL;
  447. return s;
  448. }
  449. // like trim(), but also remove duplicate spaces inside the string; may return NULL
  450. static inline char *trim_all(char *buffer) {
  451. char *d = buffer, *s = buffer;
  452. // skip spaces
  453. while(isspace(*s)) s++;
  454. while(*s) {
  455. // copy the non-space part
  456. while(*s && !isspace(*s)) *d++ = *s++;
  457. // add a space if we have to
  458. if(*s && isspace(*s)) {
  459. *d++ = ' ';
  460. s++;
  461. }
  462. // skip spaces
  463. while(isspace(*s)) s++;
  464. }
  465. *d = '\0';
  466. if(d > buffer) {
  467. d--;
  468. if(isspace(*d)) *d = '\0';
  469. }
  470. if(!buffer[0]) return NULL;
  471. return buffer;
  472. }
  473. #endif //NETDATA_INLINED_H