hash-match.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright (c) 2022-2023, smartmx <smartmx@qq.com>
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-04-03 smartmx the first version
  9. * 2023-03-02 smartmx add HASH_MATCH_NO_FOUND_ACTION api
  10. *
  11. */
  12. #ifndef _HASH_MACTH_H_
  13. #define _HASH_MACTH_H_
  14. #include "stdio.h"
  15. #include "stdint.h"
  16. #include "murmurhash3.h"
  17. #include "simplehash.h"
  18. /*
  19. * @Note: hash-match use murmur3 hash algorithm in default: https://github.com/aappleby/smhasher.
  20. * you can use your own hash algorithm by change the definition "hash_match_caculate".
  21. */
  22. #define hash_match_caculate murmurhash3_caculate32
  23. /* whether save description of hash source or not, set 0 will not save description. */
  24. #define HASH_MATCH_SAVE_DESC 0
  25. /* 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. */
  26. #define HASH_MATCH_INIT_CHECK 0
  27. /* change to your own printf function, or don't use it. */
  28. #define HASH_MATCH_PRINTF printf
  29. /* whether compare key when hash_code is same. */
  30. #define HASH_MATCH_COMPARE_KEY 1
  31. /* use string.h or self functions to compare key. */
  32. #define HASH_MATCH_USE_STRING_H 1
  33. #if HASH_MATCH_USE_STRING_H
  34. #include "string.h"
  35. #define hash_match_memcmp memcmp
  36. #define HASH_MATCH_MEMCMP_SAME 0
  37. #else
  38. #define hash_match_memcmp murmurhash3_lower_char_upper_memcmp
  39. #define HASH_MATCH_MEMCMP_SAME 0
  40. #endif
  41. typedef void (*hash_match_handler)(void *);
  42. typedef struct _hash_match_struct
  43. {
  44. const uint8_t *hash_key_src;
  45. uint32_t hash_key_len;
  46. uint32_t *hash_code;
  47. hash_match_handler handler;
  48. #if HASH_MATCH_SAVE_DESC
  49. const char *hash_desc;
  50. #endif
  51. } hash_match_t;
  52. #if HASH_MATCH_SAVE_DESC
  53. #define HASH_MATCH_EXPORT(GROUP, NAME, hash_key_src, hash_key_len, handler, hash_desc) \
  54. static const char NAME##_hash_desc[] = hash_desc; \
  55. static uint32_t NAME##_hash_code = 0; \
  56. HASH_MATCH_USED const hash_match_t NAME HASH_MATCH_SECTION(#GROUP)= \
  57. { \
  58. hash_key_src, \
  59. hash_key_len, \
  60. &NAME##_hash_code, \
  61. (hash_match_handler)&handler, \
  62. NAME##_hash_desc, \
  63. }
  64. #else
  65. /* use va_args to adapt from codes which has HASH_MATCH_SAVE_DESC enabled. */
  66. #define HASH_MATCH_EXPORT(GROUP, NAME, hash_key_src, hash_key_len, handler, ...) \
  67. static uint32_t NAME##_hash_code = 0; \
  68. HASH_MATCH_USED const hash_match_t NAME HASH_MATCH_SECTION(#GROUP)= \
  69. { \
  70. hash_key_src, \
  71. hash_key_len, \
  72. &NAME##_hash_code, \
  73. (hash_match_handler)&handler, \
  74. }
  75. #endif
  76. /* we do not use these functions directly, but use macro definitions functions instead. */
  77. extern void hash_match_group_init(const hash_match_t *start, const hash_match_t *end);
  78. extern void *hash_match_group(const hash_match_t *start, const hash_match_t *end, const void *src, uint32_t len, void *param);
  79. extern void hash_match_group_list(const hash_match_t *start, const hash_match_t *end);
  80. /* Compiler Related Definitions */
  81. #if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM Compiler */
  82. #define HASH_MATCH_SECTION(x) __attribute__((section(x)))
  83. #define HASH_MATCH_USED __attribute__((used))
  84. #define HASH_MATCH_INIT(GROUP) do \
  85. { \
  86. extern const int GROUP##$$Base; \
  87. extern const int GROUP##$$Limit; \
  88. hash_match_group_init((const hash_match_t*)&GROUP##$$Base, (const hash_match_t*)&GROUP##$$Limit); \
  89. } while(0)
  90. #define HASH_MATCH(GROUP, SRC, LEN, PARAMS) do \
  91. { \
  92. extern const int GROUP##$$Base; \
  93. extern const int GROUP##$$Limit; \
  94. hash_match_group((const hash_match_t*)&GROUP##$$Base, (const hash_match_t*)&GROUP##$$Limit, SRC, LEN, PARAMS); \
  95. } while(0)
  96. #define HASH_MATCH_NO_FOUND_ACTION(GROUP, SRC, LEN, PARAMS, NO_FOUND_ACTION) do \
  97. { \
  98. extern const int GROUP##$$Base; \
  99. extern const int GROUP##$$Limit; \
  100. if(hash_match_group((const hash_match_t*)&GROUP##$$Base, (const hash_match_t*)&GROUP##$$Limit, SRC, LEN, PARAMS) == NULL) \
  101. { \
  102. NO_FOUND_ACTION; \
  103. } \
  104. } while(0)
  105. #define HASH_MATCH_LIST(GROUP) do \
  106. { \
  107. extern const int GROUP##$$Base; \
  108. extern const int GROUP##$$Limit; \
  109. hash_match_group_list((const hash_match_t*)&GROUP##$$Base, (const hash_match_t*)&GROUP##$$Limit); \
  110. } while(0)
  111. #elif defined (__IAR_SYSTEMS_ICC__) /* for IAR Compiler */
  112. #define HASH_MATCH_SECTION(x) @ x
  113. #define HASH_MATCH_USED __root
  114. #define HASH_MATCH_INIT(GROUP) do \
  115. { \
  116. hash_match_group_init((const hash_match_t*)(__section_begin(#GROUP)), (const hash_match_t*)(__section_end(#GROUP))); \
  117. } while(0)
  118. #define HASH_MATCH(GROUP, SRC, LEN, PARAMS) do \
  119. { \
  120. hash_match_group((const hash_match_t*)(__section_begin(#GROUP)), (const hash_match_t*)(__section_end(#GROUP)), SRC, LEN, PARAMS); \
  121. } while(0)
  122. #define HASH_MATCH_NO_FOUND_ACTION(GROUP, SRC, LEN, PARAMS, NO_FOUND_ACTION) do \
  123. { \
  124. if(hash_match_group((const hash_match_t*)(__section_begin(#GROUP)), (const hash_match_t*)(__section_end(#GROUP)), SRC, LEN, PARAMS) == NULL) \
  125. { \
  126. NO_FOUND_ACTION; \
  127. } \
  128. } while(0)
  129. #define HASH_MATCH_LIST(GROUP) do \
  130. { \
  131. hash_match_group_list((const hash_match_t*)(__section_begin(#GROUP)), (const hash_match_t*)(__section_end(#GROUP))); \
  132. } while(0)
  133. #elif defined (__GNUC__) /* GNU GCC Compiler */
  134. #define HASH_MATCH_SECTION(x) __attribute__((section(x)))
  135. #define HASH_MATCH_USED __attribute__((used))
  136. #define HASH_MATCH_INIT(GROUP) do \
  137. { \
  138. extern const int GROUP##_start; \
  139. extern const int GROUP##_end; \
  140. hash_match_group_init((const hash_match_t*)&GROUP##_start, (const hash_match_t*)&GROUP##_end); \
  141. } while(0)
  142. #define HASH_MATCH(GROUP, SRC, LEN, PARAMS) do \
  143. { \
  144. extern const int GROUP##_start; \
  145. extern const int GROUP##_end; \
  146. hash_match_group((const hash_match_t*)&GROUP##_start, (const hash_match_t*)&GROUP##_end, SRC, LEN, PARAMS); \
  147. } while(0)
  148. #define HASH_MATCH_NO_FOUND_ACTION(GROUP, SRC, LEN, PARAMS, NO_FOUND_ACTION) do \
  149. { \
  150. extern const int GROUP##_start; \
  151. extern const int GROUP##_end; \
  152. if(hash_match_group((const hash_match_t*)&GROUP##_start, (const hash_match_t*)&GROUP##_end, SRC, LEN, PARAMS)== NULL) \
  153. { \
  154. NO_FOUND_ACTION; \
  155. } \
  156. } while(0)
  157. #define HASH_MATCH_LIST(GROUP) do \
  158. { \
  159. extern const int GROUP##_start; \
  160. extern const int GROUP##_end; \
  161. hash_match_group_list((const hash_match_t*)&GROUP##_start, (const hash_match_t*)&GROUP##_end); \
  162. } while(0)
  163. #else
  164. #error not supported tool chain
  165. #endif
  166. #endif