summaryrefslogtreecommitdiffstats
path: root/runtime/map.h
blob: 617ff3e2b1ee6684043de385e84f3cc43140a40c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* -*- linux-c -*- */
#include <linux/types.h>

typedef struct {
	int64_t count;
	int64_t sum;
	int64_t min, max;
	int64_t histogram[BUCKETS];
} stat;

union key_data {
	long val;
	char *str;
};

enum keytype { NONE, LONG, STR } __attribute__ ((packed));
enum valtype { INT64, STAT, STRING, END };

/* all map nodes have the following structure */
struct map_node {
	struct list_head lnode;
	struct hlist_node hnode;
	union key_data key1;
	union key_data key2;
	enum keytype key1type;
	enum keytype key2type;
};

/* specific map nodes with data attached */
struct map_node_int64 {
	struct map_node n;
	int64_t val;
};

struct map_node_str {
	struct map_node n;
	char *str;
};

struct map_node_stat {
	struct map_node n;
	stat stats;
};

struct map_root {
	/* type of the values stored in the array */
	enum valtype type;

	/* maximum number of elements allowed in the array. */
	int maxnum;

	/* current number of elements */
	int num;

	/* when more than maxnum elements, wrap or discard */
	int no_wrap;

	/* linked list of current entries */
	struct list_head head;

	/* pool of unused entries.  Used only when entries are statically allocated */
	/* at startup. */
	struct list_head pool;

	/* saved key entry for lookups */
	struct map_node *key;

	/* this is the creation data saved between the key functions and the */
	/* set/get functions */
	u_int8_t create;
	enum keytype c_key1type;
	enum keytype c_key2type;
	struct hlist_head *c_keyhead;
	union key_data c_key1;
	union key_data c_key2;

	/* the hash table for this array */
	struct hlist_head hashes[HASH_TABLE_SIZE];

	/* pointer to allocated memory space */
	void *membuf;
};

typedef struct map_root *MAP;

#define key1str(ptr) (ptr->n.key1.str)
#define key2str(ptr) (ptr->n.key2.str)
#define key1int(ptr) (ptr->n.key1.val)
#define key2int(ptr) (ptr->n.key2.val)

#define _stp_map_key2(map, key1, key2)				\
  ({								\
    if (__builtin_types_compatible_p (typeof (key1), char[]))	\
      if (__builtin_types_compatible_p (typeof (key2), char[])) \
	_stp_map_key_str_str (map, (char *)(key1), (char *)(key2));	\
      else							\
	_stp_map_key_str_long (map, (char *)(key1), (long)(key2));	\
    else							\
      if (__builtin_types_compatible_p (typeof (key2), char[])) \
	_stp_map_key_long_str (map, (long)(key1), (char *)(key2));	\
      else							\
	_stp_map_key_long_long (map, (long)(key1), (long)(key2));	\
  })

#define _stp_map_key(map, key)				\
  ({								\
    if (__builtin_types_compatible_p (typeof (key), char[]))	\
      _stp_map_key_str (map, (char *)(key));				\
    else							\
      _stp_map_key_long (map, (long)(key));				\
  })

#define _stp_map_set(map, val)				\
  ({								\
    if (__builtin_types_compatible_p (typeof (val), char[]))	\
      _stp_map_set_str (map, (char *)(val));				\
    else							\
      _stp_map_set_int64 (map, (int64_t)(val));			\
  })

#define _stp_list_add(map, val)				\
  ({								\
    if (__builtin_types_compatible_p (typeof (val), char[]))	\
      _stp_list_add_str (map, (char *)(val));				\
    else							\
      _stp_list_add_int64 (map, (int64_t)(val));			\
  })


/** Loop through all elements of a map.
 * @param map 
 * @param ptr pointer to a map_node_stat, map_node_int64 or map_node_str
 *
 * @b Example:
 * @include foreach.c
 */

#define foreach(map, ptr)				\
  for (ptr = (typeof(ptr))_stp_map_start(map); ptr; \
       ptr = (typeof(ptr))_stp_map_iter (map, (struct map_node *)ptr))