summaryrefslogtreecommitdiffstats
path: root/libnetdata/inlined.h
diff options
context:
space:
mode:
Diffstat (limited to 'libnetdata/inlined.h')
-rw-r--r--libnetdata/inlined.h460
1 files changed, 383 insertions, 77 deletions
diff --git a/libnetdata/inlined.h b/libnetdata/inlined.h
index aa7f3c21..2697b9a0 100644
--- a/libnetdata/inlined.h
+++ b/libnetdata/inlined.h
@@ -7,147 +7,391 @@
#ifdef KERNEL_32BIT
typedef uint32_t kernel_uint_t;
-#define str2kernel_uint_t(string) str2uint32_t(string)
+#define str2kernel_uint_t(string) str2uint32_t(string, NULL)
#define KERNEL_UINT_FORMAT "%u"
#else
typedef uint64_t kernel_uint_t;
-#define str2kernel_uint_t(string) str2uint64_t(string)
+#define str2kernel_uint_t(string) str2uint64_t(string, NULL)
#define KERNEL_UINT_FORMAT "%" PRIu64
#endif
-#define str2pid_t(string) str2uint32_t(string)
+#define str2pid_t(string) str2uint32_t(string, NULL)
// for faster execution, allow the compiler to inline
// these functions that are called thousands of times per second
-static inline uint32_t simple_hash(const char *name) {
+static inline uint32_t djb2_hash32(const char* name) {
unsigned char *s = (unsigned char *) name;
- uint32_t hval = 0x811c9dc5;
+ uint32_t hash = 5381;
+ while (*s)
+ hash = ((hash << 5) + hash) + (uint32_t) *s++; // hash * 33 + char
+ return hash;
+}
+
+static inline uint32_t pluginsd_parser_hash32(const char *name) {
+ unsigned char *s = (unsigned char *) name;
+ uint32_t hash = 0;
while (*s) {
- hval *= 16777619;
- hval ^= (uint32_t) *s++;
+ hash <<= 5;
+ hash += *s++ - ' ';
}
- return hval;
+ return hash;
}
-static inline uint32_t simple_uhash(const char *name) {
+// https://stackoverflow.com/a/107657
+static inline uint32_t larson_hash32(const char *name) {
unsigned char *s = (unsigned char *) name;
- uint32_t hval = 0x811c9dc5, c;
+ uint32_t hash = 0;
+ while (*s)
+ hash = hash * 101 + (uint32_t) *s++;
+ return hash;
+}
+
+// http://isthe.com/chongo/tech/comp/fnv/
+static inline uint32_t fnv1_hash32(const char *name) {
+ unsigned char *s = (unsigned char *) name;
+ uint32_t hash = 0x811c9dc5;
+ while (*s) {
+ hash *= 0x01000193; // 16777619
+ hash ^= (uint32_t) *s++;
+ }
+ return hash;
+}
+
+// http://isthe.com/chongo/tech/comp/fnv/
+static inline uint32_t fnv1a_hash32(const char *name) {
+ unsigned char *s = (unsigned char *) name;
+ uint32_t hash = 0x811c9dc5;
+ while (*s) {
+ hash ^= (uint32_t) *s++;
+ hash *= 0x01000193; // 16777619
+ }
+ return hash;
+}
+
+static inline uint32_t fnv1a_uhash32(const char *name) {
+ unsigned char *s = (unsigned char *) name;
+ uint32_t hash = 0x811c9dc5, c;
while ((c = *s++)) {
if (unlikely(c >= 'A' && c <= 'Z')) c += 'a' - 'A';
- hval *= 16777619;
- hval ^= c;
+ hash ^= c;
+ hash *= 0x01000193; // 16777619
}
- return hval;
+ return hash;
}
-static inline int str2i(const char *s) {
- int n = 0;
- char c, negative = (char)(*s == '-');
- const char *e = s + 30; // max number of character to iterate
+#define simple_hash(s) fnv1a_hash32(s)
+#define simple_uhash(s) fnv1a_uhash32(s)
- for(c = (char)((negative)?*(++s):*s); c >= '0' && c <= '9' && s < e ; c = *(++s)) {
- n *= 10;
- n += c - '0';
- }
+static uint32_t murmur32(uint32_t k) __attribute__((const));
+static inline uint32_t murmur32(uint32_t k) {
+ k ^= k >> 16;
+ k *= 0x85ebca6b;
+ k ^= k >> 13;
+ k *= 0xc2b2ae35;
+ k ^= k >> 16;
- if(unlikely(negative))
- return -n;
+ return k;
+}
- return n;
+static uint64_t murmur64(uint64_t k) __attribute__((const));
+static inline uint64_t murmur64(uint64_t k) {
+ k ^= k >> 33;
+ k *= 0xff51afd7ed558ccdUL;
+ k ^= k >> 33;
+ k *= 0xc4ceb9fe1a85ec53UL;
+ k ^= k >> 33;
+
+ return k;
}
-static inline long str2l(const char *s) {
- long n = 0;
- char c, negative = (*s == '-');
- const char *e = &s[30]; // max number of character to iterate
+static inline size_t indexing_partition(Word_t ptr, Word_t modulo) __attribute__((const));
+static inline size_t indexing_partition(Word_t ptr, Word_t modulo) {
+#ifdef ENV64BIT
+ uint64_t hash = murmur64(ptr);
+ return hash % modulo;
+#else
+ uint32_t hash = murmur32(ptr);
+ return hash % modulo;
+#endif
+}
+
+static inline unsigned int str2u(const char *s) {
+ unsigned int n = 0;
- for(c = (negative)?*(++s):*s; c >= '0' && c <= '9' && s < e ; c = *(++s)) {
- n *= 10;
- n += c - '0';
+ while(*s >= '0' && *s <= '9')
+ n = n * 10 + (*s++ - '0');
+
+ return n;
+}
+
+static inline int str2i(const char *s) {
+ if(unlikely(*s == '-')) {
+ s++;
+ return -(int) str2u(s);
+ }
+ else {
+ if(unlikely(*s == '+')) s++;
+ return (int) str2u(s);
}
+}
- if(unlikely(negative))
- return -n;
+static inline unsigned long str2ul(const char *s) {
+ unsigned long n = 0;
+
+ while(*s >= '0' && *s <= '9')
+ n = n * 10 + (*s++ - '0');
return n;
}
-static inline uint32_t str2uint32_t(const char *s) {
+static inline long str2l(const char *s) {
+ if(unlikely(*s == '-')) {
+ s++;
+ return -(long) str2ul(s);
+ }
+ else {
+ if(unlikely(*s == '+')) s++;
+ return (long) str2ul(s);
+ }
+}
+
+static inline uint32_t str2uint32_t(const char *s, char **endptr) {
uint32_t n = 0;
- char c;
- const char *e = &s[30]; // max number of character to iterate
- for(c = *s; c >= '0' && c <= '9' && s < e ; c = *(++s)) {
- n *= 10;
- n += c - '0';
- }
+ while(*s >= '0' && *s <= '9')
+ n = n * 10 + (*s++ - '0');
+
+ if(unlikely(endptr))
+ *endptr = (char *)s;
+
return n;
}
-static inline uint64_t str2uint64_t(const char *s) {
+static inline uint64_t str2uint64_t(const char *s, char **endptr) {
uint64_t n = 0;
- char c;
- const char *e = &s[30]; // max number of character to iterate
- for(c = *s; c >= '0' && c <= '9' && s < e ; c = *(++s)) {
- n *= 10;
- n += c - '0';
- }
+#ifdef ENV32BIT
+ unsigned long n32 = 0;
+ while (*s >= '0' && *s <= '9' && n32 < (ULONG_MAX / 10))
+ n32 = n32 * 10 + (*s++ - '0');
+
+ n = n32;
+#endif
+
+ while(*s >= '0' && *s <= '9')
+ n = n * 10 + (*s++ - '0');
+
+ if(unlikely(endptr))
+ *endptr = (char *)s;
+
return n;
}
-static inline unsigned long str2ul(const char *s) {
- unsigned long n = 0;
- char c;
- const char *e = &s[30]; // max number of character to iterate
+static inline unsigned long long int str2ull(const char *s, char **endptr) {
+ return str2uint64_t(s, endptr);
+}
- for(c = *s; c >= '0' && c <= '9' && s < e ; c = *(++s)) {
- n *= 10;
- n += c - '0';
+static inline long long str2ll(const char *s, char **endptr) {
+ if(unlikely(*s == '-')) {
+ s++;
+ return -(long long) str2uint64_t(s, endptr);
}
- return n;
+ else {
+ if(unlikely(*s == '+')) s++;
+ return (long long) str2uint64_t(s, endptr);
+ }
+}
+
+static inline uint64_t str2uint64_hex(const char *src, char **endptr) {
+ uint64_t num = 0;
+ const unsigned char *s = (const unsigned char *)src;
+ unsigned char c;
+
+ while ((c = hex_value_from_ascii[*s]) != 255) {
+ num = (num << 4) | c;
+ s++;
+ }
+
+ if(endptr)
+ *endptr = (char *)s;
+
+ return num;
}
-static inline unsigned long long str2ull(const char *s) {
- unsigned long long n = 0;
- char c;
- const char *e = &s[30]; // max number of character to iterate
+static inline uint64_t str2uint64_base64(const char *src, char **endptr) {
+ uint64_t num = 0;
+ const unsigned char *s = (const unsigned char *)src;
+ unsigned char c;
+
+ while ((c = base64_value_from_ascii[*s]) != 255) {
+ num = (num << 6) | c;
+ s++;
+ }
+
+ if(endptr)
+ *endptr = (char *)s;
+
+ return num;
+}
+
+static inline NETDATA_DOUBLE str2ndd_parse_double_decimal_digits_internal(const char *src, int *digits) {
+ const char *s = src;
+ NETDATA_DOUBLE n = 0.0;
+
+ while(*s >= '0' && *s <= '9') {
+
+ // this works for both 32-bit and 64-bit systems
+ unsigned long ni = 0;
+ unsigned exponent = 0;
+ while (*s >= '0' && *s <= '9' && ni < (ULONG_MAX / 10)) {
+ ni = (ni * 10) + (*s++ - '0');
+ exponent++;
+ }
- for(c = *s; c >= '0' && c <= '9' && s < e ; c = *(++s)) {
- n *= 10;
- n += c - '0';
+ n = n * powndd(10.0, exponent) + (NETDATA_DOUBLE)ni;
}
+
+ *digits = (int)(s - src);
return n;
}
-static inline long long str2ll(const char *s, char **endptr) {
- int negative = 0;
+static inline NETDATA_DOUBLE str2ndd(const char *src, char **endptr) {
+ const char *s = src;
+
+ NETDATA_DOUBLE sign = 1.0;
+ NETDATA_DOUBLE result;
+ int integral_digits = 0;
+
+ NETDATA_DOUBLE fractional = 0.0;
+ int fractional_digits = 0;
+
+ NETDATA_DOUBLE exponent = 0.0;
+ int exponent_digits = 0;
+
+ switch(*s) {
+ case '-':
+ s++;
+ sign = -1.0;
+ break;
+
+ case '+':
+ s++;
+ break;
+
+ case 'n':
+ if(s[1] == 'a' && s[2] == 'n') {
+ if(endptr) *endptr = (char *)&s[3];
+ return NAN;
+ }
+ if(s[1] == 'u' && s[2] == 'l' && s[3] == 'l') {
+ if(endptr) *endptr = (char *)&s[3];
+ return NAN;
+ }
+ break;
+
+ case 'i':
+ if(s[1] == 'n' && s[2] == 'f') {
+ if(endptr) *endptr = (char *)&s[3];
+ return INFINITY;
+ }
+ break;
+
+ default:
+ break;
+ }
- if(unlikely(*s == '-')) {
+ result = str2ndd_parse_double_decimal_digits_internal(s, &integral_digits);
+ s += integral_digits;
+
+ if(unlikely(*s == '.')) {
s++;
- negative = 1;
+ fractional = str2ndd_parse_double_decimal_digits_internal(s, &fractional_digits);
+ s += fractional_digits;
}
- else if(unlikely(*s == '+'))
+
+ if (unlikely(*s == 'e' || *s == 'E')) {
+ const char *e_ptr = s;
s++;
- long long n = 0;
- char c;
- const char *e = &s[30]; // max number of character to iterate
+ int exponent_sign = 1;
+ if (*s == '-') {
+ exponent_sign = -1;
+ s++;
+ }
+ else if(*s == '+')
+ s++;
- for(c = *s; c >= '0' && c <= '9' && s < e ; c = *(++s)) {
- n *= 10;
- n += c - '0';
+ exponent = str2ndd_parse_double_decimal_digits_internal(s, &exponent_digits);
+ if(unlikely(!exponent_digits)) {
+ exponent = 0;
+ s = e_ptr;
+ }
+ else {
+ s += exponent_digits;
+ exponent *= exponent_sign;
+ }
}
if(unlikely(endptr))
*endptr = (char *)s;
- if(unlikely(negative))
- return -n;
+ if (unlikely(exponent_digits))
+ result *= powndd(10.0, exponent);
+
+ if (unlikely(fractional_digits))
+ result += fractional / powndd(10.0, fractional_digits) * (exponent_digits ? powndd(10.0, exponent) : 1.0);
+
+ return sign * result;
+}
+
+static inline unsigned long long str2ull_encoded(const char *s) {
+ if(*s == IEEE754_UINT64_B64_PREFIX[0])
+ return str2uint64_base64(s + sizeof(IEEE754_UINT64_B64_PREFIX) - 1, NULL);
+
+ if(s[0] == HEX_PREFIX[0] && s[1] == HEX_PREFIX[1])
+ return str2uint64_hex(s + 2, NULL);
+
+ return str2uint64_t(s, NULL);
+}
+
+static inline long long str2ll_encoded(const char *s) {
+ if(*s == '-')
+ return -(long long) str2ull_encoded(&s[1]);
else
- return n;
+ return (long long) str2ull_encoded(s);
+}
+
+static inline NETDATA_DOUBLE str2ndd_encoded(const char *src, char **endptr) {
+ if (*src == IEEE754_DOUBLE_B64_PREFIX[0]) {
+ // double parsing from base64
+ uint64_t n = str2uint64_base64(src + sizeof(IEEE754_DOUBLE_B64_PREFIX) - 1, endptr);
+ NETDATA_DOUBLE *ptr = (NETDATA_DOUBLE *) (&n);
+ return *ptr;
+ }
+
+ if (*src == IEEE754_DOUBLE_HEX_PREFIX[0]) {
+ // double parsing from hex
+ uint64_t n = str2uint64_hex(src + sizeof(IEEE754_DOUBLE_HEX_PREFIX) - 1, endptr);
+ NETDATA_DOUBLE *ptr = (NETDATA_DOUBLE *) (&n);
+ return *ptr;
+ }
+
+ double sign = 1.0;
+
+ if(*src == '-') {
+ sign = -1.0;
+ src++;
+ }
+
+ if(unlikely(*src == IEEE754_UINT64_B64_PREFIX[0]))
+ return (NETDATA_DOUBLE) str2uint64_base64(src + sizeof(IEEE754_UINT64_B64_PREFIX) - 1, endptr) * sign;
+
+ if(unlikely(*src == HEX_PREFIX[0] && src[1] == HEX_PREFIX[1]))
+ return (NETDATA_DOUBLE) str2uint64_hex(src + sizeof(HEX_PREFIX) - 1, endptr) * sign;
+
+ return str2ndd(src, endptr) * sign;
}
static inline char *strncpyz(char *dst, const char *src, size_t n) {
@@ -248,7 +492,7 @@ static inline int read_single_number_file(const char *filename, unsigned long lo
}
buffer[30] = '\0';
- *result = str2ull(buffer);
+ *result = str2ull(buffer, NULL);
return 0;
}
@@ -266,4 +510,66 @@ static inline int read_single_signed_number_file(const char *filename, long long
return 0;
}
+static inline int uuid_memcmp(const uuid_t *uu1, const uuid_t *uu2) {
+ return memcmp(uu1, uu2, sizeof(uuid_t));
+}
+
+static inline char *strsep_skip_consecutive_separators(char **ptr, char *s) {
+ char *p = (char *)"";
+ while (p && !p[0] && *ptr) p = strsep(ptr, s);
+ return (p);
+}
+
+// remove leading and trailing spaces; may return NULL
+static inline char *trim(char *s) {
+ // skip leading spaces
+ while (*s && isspace(*s)) s++;
+ if (!*s) return NULL;
+
+ // skip tailing spaces
+ // this way is way faster. Writes only one NUL char.
+ ssize_t l = (ssize_t)strlen(s);
+ if (--l >= 0) {
+ char *p = s + l;
+ while (p > s && isspace(*p)) p--;
+ *++p = '\0';
+ }
+
+ if (!*s) return NULL;
+
+ return s;
+}
+
+// like trim(), but also remove duplicate spaces inside the string; may return NULL
+static inline char *trim_all(char *buffer) {
+ char *d = buffer, *s = buffer;
+
+ // skip spaces
+ while(isspace(*s)) s++;
+
+ while(*s) {
+ // copy the non-space part
+ while(*s && !isspace(*s)) *d++ = *s++;
+
+ // add a space if we have to
+ if(*s && isspace(*s)) {
+ *d++ = ' ';
+ s++;
+ }
+
+ // skip spaces
+ while(isspace(*s)) s++;
+ }
+
+ *d = '\0';
+
+ if(d > buffer) {
+ d--;
+ if(isspace(*d)) *d = '\0';
+ }
+
+ if(!buffer[0]) return NULL;
+ return buffer;
+}
+
#endif //NETDATA_INLINED_H