-
Notifications
You must be signed in to change notification settings - Fork 6
/
hash-match.h
199 lines (166 loc) · 8.83 KB
/
hash-match.h
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
* Copyright (c) 2022-2023, smartmx <smartmx@qq.com>
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2022-04-03 smartmx the first version
* 2023-03-02 smartmx add HASH_MATCH_NO_FOUND_ACTION api
*
*/
#ifndef _HASH_MACTH_H_
#define _HASH_MACTH_H_
#include "stdio.h"
#include "stdint.h"
#include "murmurhash3.h"
#include "simplehash.h"
/*
* @Note: hash-match use murmur3 hash algorithm in default: https://github.com/aappleby/smhasher.
* you can use your own hash algorithm by change the definition "hash_match_caculate".
*/
#define hash_match_caculate murmurhash3_caculate32
/* whether save description of hash source or not, set 0 will not save description. */
#define HASH_MATCH_SAVE_DESC 0
/* set HASH_MATCH_INIT_CHECK to 1 will check all hash values in one group during init a group, report if some hash value is duplicated. */
#define HASH_MATCH_INIT_CHECK 0
/* change to your own printf function, or don't use it. */
#define HASH_MATCH_PRINTF printf
/* whether compare key when hash_code is same. */
#define HASH_MATCH_COMPARE_KEY 1
/* use string.h or self functions to compare key. */
#define HASH_MATCH_USE_STRING_H 1
#if HASH_MATCH_USE_STRING_H
#include "string.h"
#define hash_match_memcmp memcmp
#define HASH_MATCH_MEMCMP_SAME 0
#else
#define hash_match_memcmp murmurhash3_lower_char_upper_memcmp
#define HASH_MATCH_MEMCMP_SAME 0
#endif
typedef void (*hash_match_handler)(void *);
typedef struct _hash_match_struct
{
const uint8_t *hash_key_src;
uint32_t hash_key_len;
uint32_t *hash_code;
hash_match_handler handler;
#if HASH_MATCH_SAVE_DESC
const char *hash_desc;
#endif
} hash_match_t;
#if HASH_MATCH_SAVE_DESC
#define HASH_MATCH_EXPORT(GROUP, NAME, hash_key_src, hash_key_len, handler, hash_desc) \
static const char NAME##_hash_desc[] = hash_desc; \
static uint32_t NAME##_hash_code = 0; \
HASH_MATCH_USED const hash_match_t NAME HASH_MATCH_SECTION(#GROUP)= \
{ \
hash_key_src, \
hash_key_len, \
&NAME##_hash_code, \
(hash_match_handler)&handler, \
NAME##_hash_desc, \
}
#else
/* use va_args to adapt from codes which has HASH_MATCH_SAVE_DESC enabled. */
#define HASH_MATCH_EXPORT(GROUP, NAME, hash_key_src, hash_key_len, handler, ...) \
static uint32_t NAME##_hash_code = 0; \
HASH_MATCH_USED const hash_match_t NAME HASH_MATCH_SECTION(#GROUP)= \
{ \
hash_key_src, \
hash_key_len, \
&NAME##_hash_code, \
(hash_match_handler)&handler, \
}
#endif
/* we do not use these functions directly, but use macro definitions functions instead. */
extern void hash_match_group_init(const hash_match_t *start, const hash_match_t *end);
extern void *hash_match_group(const hash_match_t *start, const hash_match_t *end, const void *src, uint32_t len, void *param);
extern void hash_match_group_list(const hash_match_t *start, const hash_match_t *end);
/* Compiler Related Definitions */
#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM Compiler */
#define HASH_MATCH_SECTION(x) __attribute__((section(x)))
#define HASH_MATCH_USED __attribute__((used))
#define HASH_MATCH_INIT(GROUP) do \
{ \
extern const int GROUP##$$Base; \
extern const int GROUP##$$Limit; \
hash_match_group_init((const hash_match_t*)&GROUP##$$Base, (const hash_match_t*)&GROUP##$$Limit); \
} while(0)
#define HASH_MATCH(GROUP, SRC, LEN, PARAMS) do \
{ \
extern const int GROUP##$$Base; \
extern const int GROUP##$$Limit; \
hash_match_group((const hash_match_t*)&GROUP##$$Base, (const hash_match_t*)&GROUP##$$Limit, SRC, LEN, PARAMS); \
} while(0)
#define HASH_MATCH_NO_FOUND_ACTION(GROUP, SRC, LEN, PARAMS, NO_FOUND_ACTION) do \
{ \
extern const int GROUP##$$Base; \
extern const int GROUP##$$Limit; \
if(hash_match_group((const hash_match_t*)&GROUP##$$Base, (const hash_match_t*)&GROUP##$$Limit, SRC, LEN, PARAMS) == NULL) \
{ \
NO_FOUND_ACTION; \
} \
} while(0)
#define HASH_MATCH_LIST(GROUP) do \
{ \
extern const int GROUP##$$Base; \
extern const int GROUP##$$Limit; \
hash_match_group_list((const hash_match_t*)&GROUP##$$Base, (const hash_match_t*)&GROUP##$$Limit); \
} while(0)
#elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */
#define HASH_MATCH_SECTION(x) @ x
#define HASH_MATCH_USED __root
#define HASH_MATCH_INIT(GROUP) do \
{ \
hash_match_group_init((const hash_match_t*)(__section_begin(#GROUP)), (const hash_match_t*)(__section_end(#GROUP))); \
} while(0)
#define HASH_MATCH(GROUP, SRC, LEN, PARAMS) do \
{ \
hash_match_group((const hash_match_t*)(__section_begin(#GROUP)), (const hash_match_t*)(__section_end(#GROUP)), SRC, LEN, PARAMS); \
} while(0)
#define HASH_MATCH_NO_FOUND_ACTION(GROUP, SRC, LEN, PARAMS, NO_FOUND_ACTION) do \
{ \
if(hash_match_group((const hash_match_t*)(__section_begin(#GROUP)), (const hash_match_t*)(__section_end(#GROUP)), SRC, LEN, PARAMS) == NULL) \
{ \
NO_FOUND_ACTION; \
} \
} while(0)
#define HASH_MATCH_LIST(GROUP) do \
{ \
hash_match_group_list((const hash_match_t*)(__section_begin(#GROUP)), (const hash_match_t*)(__section_end(#GROUP))); \
} while(0)
#elif defined (__GNUC__) /* GNU GCC Compiler */
#define HASH_MATCH_SECTION(x) __attribute__((section(x)))
#define HASH_MATCH_USED __attribute__((used))
#define HASH_MATCH_INIT(GROUP) do \
{ \
extern const int GROUP##_start; \
extern const int GROUP##_end; \
hash_match_group_init((const hash_match_t*)&GROUP##_start, (const hash_match_t*)&GROUP##_end); \
} while(0)
#define HASH_MATCH(GROUP, SRC, LEN, PARAMS) do \
{ \
extern const int GROUP##_start; \
extern const int GROUP##_end; \
hash_match_group((const hash_match_t*)&GROUP##_start, (const hash_match_t*)&GROUP##_end, SRC, LEN, PARAMS); \
} while(0)
#define HASH_MATCH_NO_FOUND_ACTION(GROUP, SRC, LEN, PARAMS, NO_FOUND_ACTION) do \
{ \
extern const int GROUP##_start; \
extern const int GROUP##_end; \
if(hash_match_group((const hash_match_t*)&GROUP##_start, (const hash_match_t*)&GROUP##_end, SRC, LEN, PARAMS)== NULL) \
{ \
NO_FOUND_ACTION; \
} \
} while(0)
#define HASH_MATCH_LIST(GROUP) do \
{ \
extern const int GROUP##_start; \
extern const int GROUP##_end; \
hash_match_group_list((const hash_match_t*)&GROUP##_start, (const hash_match_t*)&GROUP##_end); \
} while(0)
#else
#error not supported tool chain
#endif
#endif