1 #ifndef _DDTRACE_UTILS_H
2 #define _DDTRACE_UTILS_H
3 
4 #include <Python.h>
5 #include <stdlib.h>
6 
7 
8 static inline uint64_t
random_range(uint64_t max)9 random_range(uint64_t max)
10 {
11     /* Return a random number between [0, max[ */
12     return (uint64_t)((double)rand() / ((double)RAND_MAX + 1) * max);
13 }
14 
15 
16 #define DO_NOTHING(...)
17 
18 #define p_new(type, count) PyMem_RawMalloc(sizeof(type) * (count))
19 #define p_delete(mem_p) PyMem_Free(mem_p);
20 // Allocate at least 16 and 50% more than requested to avoid allocating items one by one.
21 #define p_alloc_nr(x) (((x) + 16) * 3 / 2)
22 #define p_realloc(p, count)                                                                                            \
23     do {                                                                                                               \
24         (p) = PyMem_RawRealloc((p), sizeof(*p) * (count));                                                             \
25     } while (0)
26 
27 #define p_grow(p, goalnb, allocnb)                                                                                     \
28     do {                                                                                                               \
29         if ((goalnb) > *(allocnb)) {                                                                                   \
30             if (p_alloc_nr(*(allocnb)) < (goalnb)) {                                                                   \
31                 *(allocnb) = (goalnb);                                                                                 \
32             } else {                                                                                                   \
33                 *(allocnb) = p_alloc_nr(*(allocnb));                                                                   \
34             }                                                                                                          \
35             p_realloc(p, *(allocnb));                                                                                  \
36         }                                                                                                              \
37     } while (0)
38 
39 /** Common array type */
40 #define ARRAY_TYPE(type_t, pfx, size_type)                                                                             \
41     typedef struct pfx##_array_t                                                                                       \
42     {                                                                                                                  \
43         type_t* tab;                                                                                                   \
44         size_type count, size;                                                                                         \
45     } pfx##_array_t;
46 
47 /** Common array functions */
48 #define ARRAY_COMMON_FUNCS(type_t, pfx, size_type, dtor)                                                               \
49     static inline void pfx##_array_init(pfx##_array_t* arr)                                                            \
50     {                                                                                                                  \
51         arr->count = 0;                                                                                                \
52         arr->size = 0;                                                                                                 \
53         arr->tab = NULL;                                                                                               \
54     }                                                                                                                  \
55     static inline pfx##_array_t* pfx##_array_new(void)                                                                 \
56     {                                                                                                                  \
57         pfx##_array_t* a = p_new(pfx##_array_t, 1);                                                                    \
58         pfx##_array_init(a);                                                                                           \
59         return a;                                                                                                      \
60     }                                                                                                                  \
61     static inline void pfx##_array_wipe(pfx##_array_t* arr)                                                            \
62     {                                                                                                                  \
63         for (size_type i = 0; i < arr->count; i++) {                                                                   \
64             dtor(arr->tab[i]);                                                                                         \
65         }                                                                                                              \
66         p_delete(arr->tab);                                                                                            \
67     }                                                                                                                  \
68     static inline void pfx##_array_delete(pfx##_array_t* arrp)                                                         \
69     {                                                                                                                  \
70         pfx##_array_wipe(arrp);                                                                                        \
71         p_delete(arrp);                                                                                                \
72     }                                                                                                                  \
73                                                                                                                        \
74     static inline void pfx##_array_grow(pfx##_array_t* arr, size_type newlen)                                          \
75     {                                                                                                                  \
76         p_grow(arr->tab, newlen, &arr->size);                                                                          \
77     }                                                                                                                  \
78     static inline void pfx##_array_splice(                                                                             \
79       pfx##_array_t* arr, size_type pos, size_type len, type_t items[], size_type count)                               \
80     {                                                                                                                  \
81         assert(pos >= 0 && len >= 0 && count >= 0);                                                                    \
82         assert(pos <= arr->count && pos + len <= arr->count);                                                          \
83         if (len != count) {                                                                                            \
84             pfx##_array_grow(arr, arr->count + count - len);                                                           \
85             memmove(arr->tab + pos + count, arr->tab + pos + len, (arr->count - pos - len) * sizeof(*items));          \
86             arr->count += count - len;                                                                                 \
87         }                                                                                                              \
88         memcpy(arr->tab + pos, items, count * sizeof(*items));                                                         \
89     }                                                                                                                  \
90     static inline type_t pfx##_array_take(pfx##_array_t* arr, size_type pos)                                           \
91     {                                                                                                                  \
92         type_t res = arr->tab[pos];                                                                                    \
93         pfx##_array_splice(arr, pos, 1, NULL, 0);                                                                      \
94         return res;                                                                                                    \
95     }                                                                                                                  \
96     static inline size_type pfx##_array_indexof(pfx##_array_t* arr, type_t* e) { return e - arr->tab; }                \
97     static inline type_t pfx##_array_remove(pfx##_array_t* arr, type_t* e)                                             \
98     {                                                                                                                  \
99         return pfx##_array_take(arr, pfx##_array_indexof(arr, e));                                                     \
100     }
101 
102 #define ARRAY_FUNCS(type_t, pfx, size_type, dtor)                                                                      \
103     ARRAY_COMMON_FUNCS(type_t, pfx, size_type, dtor)                                                                   \
104     static inline void pfx##_array_push(pfx##_array_t* arr, type_t e) { pfx##_array_splice(arr, 0, 0, &e, 1); }        \
105     static inline void pfx##_array_append(pfx##_array_t* arr, type_t e)                                                \
106     {                                                                                                                  \
107         pfx##_array_splice(arr, arr->count, 0, &e, 1);                                                                 \
108     }
109 
110 #define DO_ARRAY(type_t, pfx, size_type, dtor)                                                                         \
111     ARRAY_TYPE(type_t, pfx, size_type)                                                                                 \
112     ARRAY_FUNCS(type_t, pfx, size_type, dtor)
113 
114 #endif
115