-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathExStringSwitch.h
More file actions
134 lines (115 loc) · 3.31 KB
/
Copy pathExStringSwitch.h
File metadata and controls
134 lines (115 loc) · 3.31 KB
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
#pragma once
/*
* Fast string switch-case;
* Used hash method
* Excample using:
* char* s = "2";
STR_SWITCH(s)
{
STR_CASE("1");
STR_CASE("2");
STR_SWITCH(s)
{
STR_CASE("2");
{
printf("case 2");
}
break;
}
printf("case 1");
break;
STR_CASE("0");
printf("case 0");
break;
STR_CASE("3ab");
printf("case 3");
break;
STR_CASE("4");
printf("case 4");
break;
}
*/
#include <stdint.h>
#include <ctype.h>
inline constexpr uint32_t __StrSwitchLen(const char* const Str) { return (*Str != '\0') ? (__StrSwitchLen(Str + 1) + 1) : 0; }
inline constexpr uint32_t __StrSwitchHash(const char* const Str, uint32_t CurHash) { return (*Str != '\0') ? (__StrSwitchHash(Str + 1, CurHash * 31 + *Str)) : CurHash; }
inline constexpr uint64_t __StrSwitchStrCase(const char* const Str) { return ((uint64_t)__StrSwitchLen(Str) << 32) | (uint64_t)__StrSwitchHash(Str, 0); }
inline uint64_t __StrSwitch(const char* Str)
{
uint32_t h = 0;
const char* k = Str;
for(; *k != '\0'; k++) h = 31 * h + *k;
return ((uint64_t)(k - Str) << 32) | (uint64_t)h;
}
inline uint64_t __StrSwitchN(const char* Str, size_t Len)
{
uint32_t h = 0;
const char* k = Str, *m = Str + Len;
for(; k < m; k++) h = 31 * h + *k;
return ((uint64_t)(Len) << 32) | (uint64_t)h;
}
inline uint64_t __StrSwitchI(const char* Str)
{
uint32_t h = 0;
const char* k = Str;
for(; *k != '\0'; k++) h = 31 * h + tolower(*k);
return ((uint64_t)(k - Str) << 32) | (uint64_t)h;
}
inline uint64_t __StrSwitchNI(const char* Str, size_t Len)
{
uint32_t h = 0;
const char* k = Str, *m = Str + Len;
for(; k < m; k++) h = 31 * h + tolower(*k);
return ((uint64_t)(Len) << 32) | (uint64_t)h;
}
#define STR_SWITCH(Str) \
for(const char* ___switch_str = (Str); ___switch_str; ___switch_str = nullptr)\
switch(auto ___switch_hash = __StrSwitch(Str))
#define STR_SWITCH_I(Str) \
for(const char* ___switch_str = (Str); ___switch_str; ___switch_str = nullptr)\
switch(auto ___switch_hash = __StrSwitchI(Str))
#define STR_SWITCH_N(Str, Len) \
for(const char* ___switch_str = (Str); ___switch_str; ___switch_str = nullptr)\
switch(auto ___switch_hash = __StrSwitchN(Str, Len))
#define STR_SWITCH_NI(Str, Len) \
for(const char* ___switch_str = (Str); ___switch_str; ___switch_str = nullptr)\
switch(auto ___switch_hash = __StrSwitchNI(Str, Len))
#define STR_CASE(Str) \
{\
static const auto h = __StrSwitchStrCase(Str);\
case h:\
if((___switch_hash == h) && (memcmp(Str, ___switch_str, h >> 32) != 0)) break;\
}
/*@Str - must be string in lower case*/
#define STR_CASE_I(Str) \
{\
static const auto h = __StrSwitchStrCase(Str);\
case h:\
if((___switch_hash == h) && (memicmp(Str, ___switch_str, h >> 32) != 0)) break;\
}
#define STR_SWITCH_DEFAULT default:
/*
* Switching based on mapping string in 64-bit variable
*/
#define A8B(s, i, j) (uint64_t)(((uint64_t)((s "\0\0\0\0\0\0\0\0")[i])) << (j * 8))
#if BIGENDIAN == 1
#define STR_INT64(Str) \
(A8B(Str, 0, 0)|\
A8B(Str, 1, 1)|\
A8B(Str, 2, 2)|\
A8B(Str, 3, 3)|\
A8B(Str, 4, 4)|\
A8B(Str, 5, 5)|\
A8B(Str, 6, 6)|\
A8B(Str, 7, 7))
#else
#define STR_INT64(Str) \
(A8B(Str, 0, 7)|\
A8B(Str, 1, 6)|\
A8B(Str, 2, 5)|\
A8B(Str, 3, 4)|\
A8B(Str, 4, 3)|\
A8B(Str, 5, 2)|\
A8B(Str, 6, 1)|\
A8B(Str, 7, 0))
#endif