1
0

y_stringhash.inc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. #if defined _INC_y_stringhash
  2. #endinput
  3. #endif
  4. #define _INC_y_stringhash
  5. /**
  6. * <library name="y_stringhash">
  7. * <section>
  8. * Description
  9. * </section>
  10. * Allows you to hash strings at compile time to use them in a switch.
  11. * <section>
  12. * Version
  13. * </section>
  14. * 2.0
  15. * <section>
  16. * Functions
  17. * </section>
  18. * <subsection>
  19. * Stock
  20. * </subsection><ul>
  21. * <symbol name="YHash">Generate a string hash at run time.</symbol>
  22. * </ul><section>
  23. * Definitions
  24. * </section><ul>
  25. * <symbol name="_H">Generate a string hash at compile time.</symbol>
  26. * <symbol name="_I">Generate a case insensitive string hash at compile time.</symbol>
  27. * </ul>
  28. * </library>
  29. *//** *//*
  30. Legal:
  31. Version: MPL 1.1
  32. The contents of this file are subject to the Mozilla Public License Version
  33. 1.1 the "License"; you may not use this file except in compliance with
  34. the License. You may obtain a copy of the License at
  35. http://www.mozilla.org/MPL/
  36. Software distributed under the License is distributed on an "AS IS" basis,
  37. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  38. for the specific language governing rights and limitations under the
  39. License.
  40. The Original Code is the YSI framework.
  41. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  42. Portions created by the Initial Developer are Copyright C 2011
  43. the Initial Developer. All Rights Reserved.
  44. Contributors:
  45. Y_Less
  46. koolk
  47. JoeBullet/Google63
  48. g_aSlice/Slice
  49. Misiur
  50. samphunter
  51. tianmeta
  52. maddinat0r
  53. spacemud
  54. Crayder
  55. Dayvison
  56. Ahmad45123
  57. Zeex
  58. irinel1996
  59. Yiin-
  60. Chaprnks
  61. Konstantinos
  62. Masterchen09
  63. Southclaws
  64. PatchwerkQWER
  65. m0k1
  66. paulommu
  67. udan111
  68. Thanks:
  69. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  70. ZeeX - Very productive conversations.
  71. koolk - IsPlayerinAreaEx code.
  72. TheAlpha - Danish translation.
  73. breadfish - German translation.
  74. Fireburn - Dutch translation.
  75. yom - French translation.
  76. 50p - Polish translation.
  77. Zamaroht - Spanish translation.
  78. Los - Portuguese translation.
  79. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes for
  80. me to strive to better.
  81. Pixels^ - Running XScripters where the idea was born.
  82. Matite - Pestering me to release it and using it.
  83. Very special thanks to:
  84. Thiadmer - PAWN, whose limits continue to amaze me!
  85. Kye/Kalcor - SA:MP.
  86. SA:MP Team past, present and future - SA:MP.
  87. Optional plugins:
  88. Gamer_Z - GPS.
  89. Incognito - Streamer.
  90. Me - sscanf2, fixes2, Whirlpool.
  91. */
  92. #include "..\YSI_Internal\y_version"
  93. #include "..\YSI_Core\y_debug"
  94. // Note: H_a, H_b, H_c, H_d, H_f and H_g are defined here, H_e in y_amx, H_z in
  95. // y_masteronce, H_u in y_users, H_y in y_timers.
  96. // ===================
  97. // Determine version
  98. // ===================
  99. // Entry.
  100. #define _H (_:_H_1:_H_0
  101. #define _I (_:_H_3:_H_2
  102. #define _H@b (_:_H_1:_H_0
  103. #define _I@b (_:_H_3:_H_2
  104. // Old.
  105. #define _H_0(%0) HASH@bernstein(%0))
  106. #define _H_2(%0) HASHi@bernstein(%0))
  107. // New.
  108. #define _H_1:_H_0<%0> HASh@bernstein(%0))
  109. #define _H_3:_H_2<%0> HAShi@bernstein(%0))
  110. // Entry.
  111. #define _H@f (_:_H0@f:_H1@f
  112. #define _I@f (_:_H2@f:_H3@f
  113. // Old.
  114. #define _H1@f(%0) HASH@fnv1(%0))
  115. #define _H3@f(%0) HASHi@fnv1(%0))
  116. // New.
  117. #define _H0@f:_H1@f<%0> HASh@fnv1(%0))
  118. #define _H2@f:_H3@f<%0> HAShi@fnv1(%0))
  119. // Entry.
  120. #define _H@a (_:_H0@a:_H1@a
  121. #define _I@a (_:_H2@a:_H3@a
  122. // Old.
  123. #define _H1@a(%0) HASH@fnv1a(%0))
  124. #define _H3@a(%0) HASHi@fnv1a(%0))
  125. // New.
  126. #define _H0@a:_H1@a<%0> HASh@fnv1a(%0))
  127. #define _H2@a:_H3@a<%0> HAShi@fnv1a(%0))
  128. // Entry.
  129. #define HASH (_:_H_4:_H_5
  130. #define HASHi (_:_H_6:_H_7
  131. // Old.
  132. #define _H_5(%0,%1) HASH@%0(%1))
  133. #define _H_7(%0,%1) HASHi@%0(%1))
  134. // New.
  135. #define _H_4:_H_5:%0<%1> HASh@%0(%1))
  136. #define _H_6:_H_7:%0<%1> HAShi@%0(%1))
  137. // Empty strings.
  138. #define HASH_:%0(,@,@) 2166136261
  139. #define _Y_HASH_H(%0,%1)(%9) @B%0:@A0:@A1:@A2:@A3:@A4:@A5:@A6:@A7:@A8:@A9:@Aa:@Ab:@Ac:@Ad:@Ae:@Af:@Ag:@Ah:@Ai:@Aj:@Ak:@Al:@Am:@An:@Ao:@Ap:@Aq:@Ar:@As:@At:@Au:@Av:@Aw:@Ax:@Ay:@Az:@AA:@AB:@AC:@AD:@AE:@AF:@AG:@AH:@AI:@AJ:@AK:@AL:@AM:@AN:@AO:@AP:@AQ:@AR:@AS:@AT:@AU:@AV:@AW:@AX:@AY:@AZ:@A_:@A@:@B_:@B%1$(%9)$
  140. #define _Y_HASH_I(%0,%1)(%9) @B%0:@A0:@A1:@A2:@A3:@A4:@A5:@A6:@A7:@A8:@A9:@Ba:@Bb:@Bc:@Bd:@Be:@Bf:@Bg:@Bh:@Bi:@Bj:@Bk:@Bl:@Bm:@Bn:@Bo:@Bp:@Bq:@Br:@Bs:@Bt:@Bu:@Bv:@Bw:@Bx:@By:@Bz:@AA:@AB:@AC:@AD:@AE:@AF:@AG:@AH:@AI:@AJ:@AK:@AL:@AM:@AN:@AO:@AP:@AQ:@AR:@AS:@AT:@AU:@AV:@AW:@AX:@AY:@AZ:@A_:@A@:@B_:@B%1$(%9)$
  141. // Bernstein
  142. #define @B0:%9$()$ -1
  143. #define @B1$(<%0>%1) @B2:%0@B3:<>%1
  144. #define @B2:%9<%0>%1) %9(@B2:%0)*33+%1)
  145. #define @B3:(%0)*%1$ -%1
  146. // FNV1
  147. #define @B4:%9$()$ 2166136261
  148. #define @B5$(<%0>%1) @B6:%0@B7:<>%1
  149. #define @B6:%9<%0>%1) %9(@B6:%0)*16777619^%1)
  150. #define @B7:(%0)*%9^%1$ 84696351^%1
  151. // FNV1a
  152. #define @B8:%9$()$ 2166136261
  153. #define @B9$(<%0>%1) (@BA:%0@BB:<>%1>
  154. #define @BA:%9<%0>%1>%2) %9(@BA:%0^%1)*16777619>%2)
  155. #define @BB:(%0^%1)%2>$ 2166136261^%1)%2
  156. // Entries
  157. #define HASh@bernstein(%9) _Y_HASH_H(0,1)(%9)
  158. #define HAShi@bernstein(%9) _Y_HASH_I(0,1)(%9)
  159. #define HASh@fnv1(%9) _Y_HASH_H(4,5)(%9)
  160. #define HAShi@fnv1(%9) _Y_HASH_I(4,5)(%9)
  161. #define HASh@fnv1a(%9) _Y_HASH_H(8,9)(%9)
  162. #define HAShi@fnv1a(%9) _Y_HASH_I(8,9)(%9)
  163. /*
  164. 888b 88 ,ad8888ba, 88
  165. 8888b 88 d8"' `"8b 88
  166. 88 `8b 88 d8' 88
  167. 88 `8b 88 ,adPPYba, 8b db d8 88 ,adPPYYba, ,adPPYba, ,adPPYba, ,adPPYb,88
  168. 88 `8b 88 a8P_____88 `8b d88b d8' 88 "" `Y8 I8[ "" a8P_____88 a8" `Y88
  169. 88 `8b 88 8PP""""""" `8b d8'`8b d8' Y8, ,adPPPPP88 `"Y8ba, 8PP""""""" 8b 88
  170. 88 `8888 "8b, ,aa `8bd8' `8bd8' Y8a. .a8P 88, ,88 aa ]8I "8b, ,aa "8a, ,d88
  171. 88 `888 `"Ybbd8"' YP YP `"Y8888Y"' `"8bbdP"Y8 `"YbbdP"' `"Ybbd8"' `"8bbdP"Y8
  172. */
  173. // ================
  174. // Case sensitive
  175. // ================
  176. // Test for the current character. Numbers MUST be first!
  177. #define @A0:%9$(%10%0)$ @A0:%9$(<%1>'0'%0)$
  178. #define @A1:%9$(%11%0)$ @A1:%9$(<%1>'1'%0)$
  179. #define @A2:%9$(%12%0)$ @A2:%9$(<%1>'2'%0)$
  180. #define @A3:%9$(%13%0)$ @A3:%9$(<%1>'3'%0)$
  181. #define @A4:%9$(%14%0)$ @A4:%9$(<%1>'4'%0)$
  182. #define @A5:%9$(%15%0)$ @A5:%9$(<%1>'5'%0)$
  183. #define @A6:%9$(%16%0)$ @A6:%9$(<%1>'6'%0)$
  184. #define @A7:%9$(%17%0)$ @A7:%9$(<%1>'7'%0)$
  185. #define @A8:%9$(%18%0)$ @A8:%9$(<%1>'8'%0)$
  186. #define @A9:%9$(%19%0)$ @A9:%9$(<%1>'9'%0)$
  187. #define @Aa:%9$(%1a%0)$ @Aa:%9$(<%1>97%0)$
  188. #define @Ab:%9$(%1b%0)$ @Ab:%9$(<%1>98%0)$
  189. #define @Ac:%9$(%1c%0)$ @Ac:%9$(<%1>99%0)$
  190. #define @Ad:%9$(%1d%0)$ @Ad:%9$(<%1>100%0)$
  191. #define @Ae:%9$(%1e%0)$ @Ae:%9$(<%1>101%0)$
  192. #define @Af:%9$(%1f%0)$ @Af:%9$(<%1>102%0)$
  193. #define @Ag:%9$(%1g%0)$ @Ag:%9$(<%1>103%0)$
  194. #define @Ah:%9$(%1h%0)$ @Ah:%9$(<%1>104%0)$
  195. #define @Ai:%9$(%1i%0)$ @Ai:%9$(<%1>105%0)$
  196. #define @Aj:%9$(%1j%0)$ @Aj:%9$(<%1>106%0)$
  197. #define @Ak:%9$(%1k%0)$ @Ak:%9$(<%1>107%0)$
  198. #define @Al:%9$(%1l%0)$ @Al:%9$(<%1>108%0)$
  199. #define @Am:%9$(%1m%0)$ @Am:%9$(<%1>109%0)$
  200. #define @An:%9$(%1n%0)$ @An:%9$(<%1>110%0)$
  201. #define @Ao:%9$(%1o%0)$ @Ao:%9$(<%1>111%0)$
  202. #define @Ap:%9$(%1p%0)$ @Ap:%9$(<%1>112%0)$
  203. #define @Aq:%9$(%1q%0)$ @Aq:%9$(<%1>113%0)$
  204. #define @Ar:%9$(%1r%0)$ @Ar:%9$(<%1>114%0)$
  205. #define @As:%9$(%1s%0)$ @As:%9$(<%1>115%0)$
  206. #define @At:%9$(%1t%0)$ @At:%9$(<%1>116%0)$
  207. #define @Au:%9$(%1u%0)$ @Au:%9$(<%1>117%0)$
  208. #define @Av:%9$(%1v%0)$ @Av:%9$(<%1>118%0)$
  209. #define @Aw:%9$(%1w%0)$ @Aw:%9$(<%1>119%0)$
  210. #define @Ax:%9$(%1x%0)$ @Ax:%9$(<%1>120%0)$
  211. #define @Ay:%9$(%1y%0)$ @Ay:%9$(<%1>121%0)$
  212. #define @Az:%9$(%1z%0)$ @Az:%9$(<%1>122%0)$
  213. #define @AA:%9$(%1A%0)$ @AA:%9$(<%1>65%0)$
  214. #define @AB:%9$(%1B%0)$ @AB:%9$(<%1>66%0)$
  215. #define @AC:%9$(%1C%0)$ @AC:%9$(<%1>67%0)$
  216. #define @AD:%9$(%1D%0)$ @AD:%9$(<%1>68%0)$
  217. #define @AE:%9$(%1E%0)$ @AE:%9$(<%1>69%0)$
  218. #define @AF:%9$(%1F%0)$ @AF:%9$(<%1>70%0)$
  219. #define @AG:%9$(%1G%0)$ @AG:%9$(<%1>71%0)$
  220. #define @AH:%9$(%1H%0)$ @AH:%9$(<%1>72%0)$
  221. #define @AI:%9$(%1I%0)$ @AI:%9$(<%1>73%0)$
  222. #define @AJ:%9$(%1J%0)$ @AJ:%9$(<%1>74%0)$
  223. #define @AK:%9$(%1K%0)$ @AK:%9$(<%1>75%0)$
  224. #define @AL:%9$(%1L%0)$ @AL:%9$(<%1>76%0)$
  225. #define @AM:%9$(%1M%0)$ @AM:%9$(<%1>77%0)$
  226. #define @AN:%9$(%1N%0)$ @AN:%9$(<%1>78%0)$
  227. #define @AO:%9$(%1O%0)$ @AO:%9$(<%1>79%0)$
  228. #define @AP:%9$(%1P%0)$ @AP:%9$(<%1>80%0)$
  229. #define @AQ:%9$(%1Q%0)$ @AQ:%9$(<%1>81%0)$
  230. #define @AR:%9$(%1R%0)$ @AR:%9$(<%1>82%0)$
  231. #define @AS:%9$(%1S%0)$ @AS:%9$(<%1>83%0)$
  232. #define @AT:%9$(%1T%0)$ @AT:%9$(<%1>84%0)$
  233. #define @AU:%9$(%1U%0)$ @AU:%9$(<%1>85%0)$
  234. #define @AV:%9$(%1V%0)$ @AV:%9$(<%1>86%0)$
  235. #define @AW:%9$(%1W%0)$ @AW:%9$(<%1>87%0)$
  236. #define @AX:%9$(%1X%0)$ @AX:%9$(<%1>88%0)$
  237. #define @AY:%9$(%1Y%0)$ @AY:%9$(<%1>89%0)$
  238. #define @AZ:%9$(%1Z%0)$ @AZ:%9$(<%1>90%0)$
  239. #define @A_:%9$(%1_%0)$ @A_:%9$(<%1>95%0)$
  240. #define @A@:%9$(%1@%0)$ @A@:%9$(<%1>64%0)$
  241. #define @B_:%9$(%1\32;%0)$ @B_:%9$(<%1>32%0)$
  242. // ==================
  243. // Case insensitive
  244. // ==================
  245. #define @Ba:%9$(%1a%0)$ @Ba:%9$(<%1>65%0)$
  246. #define @Bb:%9$(%1b%0)$ @Bb:%9$(<%1>66%0)$
  247. #define @Bc:%9$(%1c%0)$ @Bc:%9$(<%1>67%0)$
  248. #define @Bd:%9$(%1d%0)$ @Bd:%9$(<%1>68%0)$
  249. #define @Be:%9$(%1e%0)$ @Be:%9$(<%1>69%0)$
  250. #define @Bf:%9$(%1f%0)$ @Bf:%9$(<%1>70%0)$
  251. #define @Bg:%9$(%1g%0)$ @Bg:%9$(<%1>71%0)$
  252. #define @Bh:%9$(%1h%0)$ @Bh:%9$(<%1>72%0)$
  253. #define @Bi:%9$(%1i%0)$ @Bi:%9$(<%1>73%0)$
  254. #define @Bj:%9$(%1j%0)$ @Bj:%9$(<%1>74%0)$
  255. #define @Bk:%9$(%1k%0)$ @Bk:%9$(<%1>75%0)$
  256. #define @Bl:%9$(%1l%0)$ @Bl:%9$(<%1>76%0)$
  257. #define @Bm:%9$(%1m%0)$ @Bm:%9$(<%1>77%0)$
  258. #define @Bn:%9$(%1n%0)$ @Bn:%9$(<%1>78%0)$
  259. #define @Bo:%9$(%1o%0)$ @Bo:%9$(<%1>79%0)$
  260. #define @Bp:%9$(%1p%0)$ @Bp:%9$(<%1>80%0)$
  261. #define @Bq:%9$(%1q%0)$ @Bq:%9$(<%1>81%0)$
  262. #define @Br:%9$(%1r%0)$ @Br:%9$(<%1>82%0)$
  263. #define @Bs:%9$(%1s%0)$ @Bs:%9$(<%1>83%0)$
  264. #define @Bt:%9$(%1t%0)$ @Bt:%9$(<%1>84%0)$
  265. #define @Bu:%9$(%1u%0)$ @Bu:%9$(<%1>85%0)$
  266. #define @Bv:%9$(%1v%0)$ @Bv:%9$(<%1>86%0)$
  267. #define @Bw:%9$(%1w%0)$ @Bw:%9$(<%1>87%0)$
  268. #define @Bx:%9$(%1x%0)$ @Bx:%9$(<%1>88%0)$
  269. #define @By:%9$(%1y%0)$ @By:%9$(<%1>89%0)$
  270. #define @Bz:%9$(%1z%0)$ @Bz:%9$(<%1>90%0)$
  271. // ============
  272. // Other code
  273. // ============
  274. enum e_HASH_TYPE
  275. {
  276. hash_bernstein,
  277. hash_fnv1,
  278. hash_fnv1a
  279. }
  280. /*-------------------------------------------------------------------------*//**
  281. * <param name="str">The string to hash.</param>
  282. * <param name="sensitive">Wether the hash is case sensitive or not.</param>
  283. * <returns>
  284. * The reverse Bernstein hash of the string.
  285. * </returns>
  286. * <remarks>
  287. * Based on Bernstein hash, but backwards to match the macros. The only
  288. * characters which can be used in the compile time version of this code are:
  289. * a-z, A-Z, 0-9, _ and space.
  290. *
  291. * native Hash(str[]);
  292. *
  293. * NOW FORWARD AGAIN.
  294. * </remarks>
  295. *//*------------------------------------------------------------------------**/
  296. stock YHash(const str[], bool:sensitive = true, e_HASH_TYPE:type = hash_bernstein, len = -1, pack = false)
  297. {
  298. #pragma unused pack
  299. P:3("YHash called: \"%s\", %i, %i, %i, %i", str, _:sensitive, _:type, len, pack);
  300. //pack = str[0] > 255;
  301. if (len < 0) len = strlen(str);
  302. else len = min(len, strlen(str));
  303. new
  304. i = 0;
  305. if (str[0] > 255)
  306. {
  307. switch (type)
  308. {
  309. case hash_bernstein:
  310. {
  311. new
  312. hash = -1;
  313. if (sensitive)
  314. {
  315. while (i != len)
  316. {
  317. hash = hash * 33 + str{i++};
  318. }
  319. }
  320. else
  321. {
  322. while (i != len)
  323. {
  324. hash = hash * 33 + toupper(str{i++});
  325. }
  326. }
  327. return hash;
  328. }
  329. case hash_fnv1:
  330. {
  331. new
  332. hash = 2166136261;
  333. if (sensitive)
  334. {
  335. while (i != len)
  336. {
  337. hash = hash * 16777619 ^ str{i++};
  338. }
  339. }
  340. else
  341. {
  342. while (i != len)
  343. {
  344. hash = hash * 16777619 ^ toupper(str{i++});
  345. }
  346. }
  347. return hash;
  348. }
  349. case hash_fnv1a:
  350. {
  351. new
  352. hash = 2166136261;
  353. if (sensitive)
  354. {
  355. while (i != len)
  356. {
  357. hash = (hash ^ str{i++}) * 16777619;
  358. }
  359. }
  360. else
  361. {
  362. while (i != len)
  363. {
  364. hash = (hash ^ toupper(str{i++})) * 16777619;
  365. }
  366. }
  367. return hash;
  368. }
  369. }
  370. }
  371. else
  372. {
  373. switch (type)
  374. {
  375. case hash_bernstein:
  376. {
  377. new
  378. hash = -1;
  379. if (sensitive)
  380. {
  381. while (i != len)
  382. {
  383. hash = hash * 33 + str[i++];
  384. }
  385. }
  386. else
  387. {
  388. while (i != len)
  389. {
  390. //printf("hash: %d, old: %d, add: %d", hash, str[i], toupper(str[i]));
  391. hash = hash * 33 + toupper(str[i++]);
  392. }
  393. }
  394. return hash;
  395. }
  396. case hash_fnv1:
  397. {
  398. new
  399. hash = 2166136261;
  400. if (sensitive)
  401. {
  402. while (i != len)
  403. {
  404. hash = hash * 16777619 ^ str[i++];
  405. }
  406. }
  407. else
  408. {
  409. while (i != len)
  410. {
  411. hash = hash * 16777619 ^ toupper(str[i++]);
  412. }
  413. }
  414. return hash;
  415. }
  416. case hash_fnv1a:
  417. {
  418. new
  419. hash = 2166136261;
  420. if (sensitive)
  421. {
  422. while (i != len)
  423. {
  424. hash = (hash ^ str[i++]) * 16777619;
  425. }
  426. }
  427. else
  428. {
  429. while (i != len)
  430. {
  431. hash = (hash ^ toupper(str[i++])) * 16777619;
  432. }
  433. }
  434. return hash;
  435. }
  436. }
  437. }
  438. return -1;
  439. }
  440. #include "y_stringhash/bernstein"
  441. #include "y_stringhash/fnv1a"
  442. #include "y_stringhash/fnv1"
  443. #if defined YSI_TESTS
  444. #include "..\YSI_Core\y_testing"
  445. #include "y_stringhash/tests"
  446. #endif