makecasefoldhashtable.pl 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #!/usr/bin/perl -w
  2. # Simple DirectMedia Layer
  3. # Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
  4. #
  5. # This software is provided 'as-is', without any express or implied
  6. # warranty. In no event will the authors be held liable for any damages
  7. # arising from the use of this software.
  8. #
  9. # Permission is granted to anyone to use this software for any purpose,
  10. # including commercial applications, and to alter it and redistribute it
  11. # freely, subject to the following restrictions:
  12. #
  13. # 1. The origin of this software must not be misrepresented; you must not
  14. # claim that you wrote the original software. If you use this software
  15. # in a product, an acknowledgment in the product documentation would be
  16. # appreciated but is not required.
  17. # 2. Altered source versions must be plainly marked as such, and must not be
  18. # misrepresented as being the original software.
  19. # 3. This notice may not be removed or altered from any source distribution.
  20. # This script was originally written by Ryan C. Gordon for PhysicsFS
  21. # ( https://icculus.org/physfs/ ), under the zlib license: the same license
  22. # that SDL itself uses).
  23. use warnings;
  24. use strict;
  25. my $HASHBUCKETS1_16 = 256;
  26. my $HASHBUCKETS1_32 = 16;
  27. my $HASHBUCKETS2_16 = 16;
  28. my $HASHBUCKETS3_16 = 4;
  29. my $mem_used = 0;
  30. print <<__EOF__;
  31. /*
  32. Simple DirectMedia Layer
  33. Copyright (C) 1997-2024 Sam Lantinga <slouken\@libsdl.org>
  34. This software is provided 'as-is', without any express or implied
  35. warranty. In no event will the authors be held liable for any damages
  36. arising from the use of this software.
  37. Permission is granted to anyone to use this software for any purpose,
  38. including commercial applications, and to alter it and redistribute it
  39. freely, subject to the following restrictions:
  40. 1. The origin of this software must not be misrepresented; you must not
  41. claim that you wrote the original software. If you use this software
  42. in a product, an acknowledgment in the product documentation would be
  43. appreciated but is not required.
  44. 2. Altered source versions must be plainly marked as such, and must not be
  45. misrepresented as being the original software.
  46. 3. This notice may not be removed or altered from any source distribution.
  47. */
  48. /*
  49. * This data was generated by SDL/build-scripts/makecasefoldhashtable.pl
  50. *
  51. * Do not manually edit this file!
  52. */
  53. #ifndef SDL_casefolding_h_
  54. #define SDL_casefolding_h_
  55. /* We build three simple hashmaps here: one that maps Unicode codepoints to
  56. a one, two, or three lowercase codepoints. To retrieve this info: look at
  57. case_fold_hashX, where X is 1, 2, or 3. Most foldable codepoints fold to one,
  58. a few dozen fold to two, and a handful fold to three. If the codepoint isn't
  59. in any of these hashes, it doesn't fold (no separate upper and lowercase).
  60. Almost all these codepoints fit into 16 bits, so we hash them as such to save
  61. memory. If a codepoint is > 0xFFFF, we have separate hashes for them,
  62. since there are (currently) only about 120 of them and (currently) all of them
  63. map to a single lowercase codepoint. */
  64. typedef struct CaseFoldMapping1_32
  65. {
  66. Uint32 from;
  67. Uint32 to0;
  68. } CaseFoldMapping1_32;
  69. typedef struct CaseFoldMapping1_16
  70. {
  71. Uint16 from;
  72. Uint16 to0;
  73. } CaseFoldMapping1_16;
  74. typedef struct CaseFoldMapping2_16
  75. {
  76. Uint16 from;
  77. Uint16 to0;
  78. Uint16 to1;
  79. } CaseFoldMapping2_16;
  80. typedef struct CaseFoldMapping3_16
  81. {
  82. Uint16 from;
  83. Uint16 to0;
  84. Uint16 to1;
  85. Uint16 to2;
  86. } CaseFoldMapping3_16;
  87. typedef struct CaseFoldHashBucket1_16
  88. {
  89. const CaseFoldMapping1_16 *list;
  90. const Uint8 count;
  91. } CaseFoldHashBucket1_16;
  92. typedef struct CaseFoldHashBucket1_32
  93. {
  94. const CaseFoldMapping1_32 *list;
  95. const Uint8 count;
  96. } CaseFoldHashBucket1_32;
  97. typedef struct CaseFoldHashBucket2_16
  98. {
  99. const CaseFoldMapping2_16 *list;
  100. const Uint8 count;
  101. } CaseFoldHashBucket2_16;
  102. typedef struct CaseFoldHashBucket3_16
  103. {
  104. const CaseFoldMapping3_16 *list;
  105. const Uint8 count;
  106. } CaseFoldHashBucket3_16;
  107. __EOF__
  108. my @foldPairs1_16;
  109. my @foldPairs2_16;
  110. my @foldPairs3_16;
  111. my @foldPairs1_32;
  112. for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) {
  113. $foldPairs1_16[$i] = '';
  114. }
  115. for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) {
  116. $foldPairs1_32[$i] = '';
  117. }
  118. for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) {
  119. $foldPairs2_16[$i] = '';
  120. }
  121. for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) {
  122. $foldPairs3_16[$i] = '';
  123. }
  124. open(FH,'<','casefolding.txt') or die("failed to open casefolding.txt: $!\n");
  125. while (<FH>) {
  126. chomp;
  127. # strip comments from textfile...
  128. s/\#.*\Z//;
  129. # strip whitespace...
  130. s/\A\s+//;
  131. s/\s+\Z//;
  132. next if not /\A([a-fA-F0-9]+)\;\s*(.)\;\s*(.+)\;/;
  133. my ($code, $status, $mapping) = ($1, $2, $3);
  134. my $hexxed = hex($code);
  135. #print("// code '$code' status '$status' mapping '$mapping'\n");
  136. if (($status eq 'C') or ($status eq 'F')) {
  137. my ($map1, $map2, $map3) = (undef, undef, undef);
  138. $map1 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
  139. $map2 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
  140. $map3 = $1 if $mapping =~ s/\A([a-fA-F0-9]+)(\s*|\Z)//;
  141. die("mapping space too small for '$code'\n") if ($mapping ne '');
  142. die("problem parsing mapping for '$code'\n") if (not defined($map1));
  143. if ($hexxed < 128) {
  144. # Just ignore these, we'll handle the low-ASCII ones ourselves.
  145. } elsif ($hexxed > 0xFFFF) {
  146. # We just need to add the 32-bit 2 and/or 3 codepoint maps if this die()'s here.
  147. die("Uhoh, a codepoint > 0xFFFF that folds to multiple codepoints! Fixme.") if defined($map2);
  148. my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS1_32-1));
  149. #print("// hexxed '$hexxed' hashed1 '$hashed'\n");
  150. $foldPairs1_32[$hashed] .= " { 0x$code, 0x$map1 },\n";
  151. $mem_used += 8;
  152. } elsif (not defined($map2)) {
  153. my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS1_16-1));
  154. #print("// hexxed '$hexxed' hashed1 '$hashed'\n");
  155. $foldPairs1_16[$hashed] .= " { 0x$code, 0x$map1 },\n";
  156. $mem_used += 4;
  157. } elsif (not defined($map3)) {
  158. my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS2_16-1));
  159. #print("// hexxed '$hexxed' hashed2 '$hashed'\n");
  160. $foldPairs2_16[$hashed] .= " { 0x$code, 0x$map1, 0x$map2 },\n";
  161. $mem_used += 6;
  162. } else {
  163. my $hashed = (($hexxed ^ ($hexxed >> 8)) & ($HASHBUCKETS3_16-1));
  164. #print("// hexxed '$hexxed' hashed3 '$hashed'\n");
  165. $foldPairs3_16[$hashed] .= " { 0x$code, 0x$map1, 0x$map2, 0x$map3 },\n";
  166. $mem_used += 8;
  167. }
  168. }
  169. }
  170. close(FH);
  171. for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) {
  172. $foldPairs1_16[$i] =~ s/,\n\Z//;
  173. my $str = $foldPairs1_16[$i];
  174. next if $str eq '';
  175. my $num = '000' . $i;
  176. $num =~ s/\A.*?(\d\d\d)\Z/$1/;
  177. my $sym = "case_fold1_16_${num}";
  178. print("static const CaseFoldMapping1_16 ${sym}[] = {\n$str\n};\n\n");
  179. }
  180. for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) {
  181. $foldPairs1_32[$i] =~ s/,\n\Z//;
  182. my $str = $foldPairs1_32[$i];
  183. next if $str eq '';
  184. my $num = '000' . $i;
  185. $num =~ s/\A.*?(\d\d\d)\Z/$1/;
  186. my $sym = "case_fold1_32_${num}";
  187. print("static const CaseFoldMapping1_32 ${sym}[] = {\n$str\n};\n\n");
  188. }
  189. for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) {
  190. $foldPairs2_16[$i] =~ s/,\n\Z//;
  191. my $str = $foldPairs2_16[$i];
  192. next if $str eq '';
  193. my $num = '000' . $i;
  194. $num =~ s/\A.*?(\d\d\d)\Z/$1/;
  195. my $sym = "case_fold2_16_${num}";
  196. print("static const CaseFoldMapping2_16 ${sym}[] = {\n$str\n};\n\n");
  197. }
  198. for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) {
  199. $foldPairs3_16[$i] =~ s/,\n\Z//;
  200. my $str = $foldPairs3_16[$i];
  201. next if $str eq '';
  202. my $num = '000' . $i;
  203. $num =~ s/\A.*?(\d\d\d)\Z/$1/;
  204. my $sym = "case_fold3_16_${num}";
  205. print("static const CaseFoldMapping3_16 ${sym}[] = {\n$str\n};\n\n");
  206. }
  207. print("static const CaseFoldHashBucket1_16 case_fold_hash1_16[] = {\n");
  208. for (my $i = 0; $i < $HASHBUCKETS1_16; $i++) {
  209. my $str = $foldPairs1_16[$i];
  210. if ($str eq '') {
  211. print(" { NULL, 0 },\n");
  212. } else {
  213. my $num = '000' . $i;
  214. $num =~ s/\A.*?(\d\d\d)\Z/$1/;
  215. my $sym = "case_fold1_16_${num}";
  216. print(" { $sym, SDL_arraysize($sym) },\n");
  217. }
  218. $mem_used += 12;
  219. }
  220. print("};\n\n");
  221. print("static const CaseFoldHashBucket1_32 case_fold_hash1_32[] = {\n");
  222. for (my $i = 0; $i < $HASHBUCKETS1_32; $i++) {
  223. my $str = $foldPairs1_32[$i];
  224. if ($str eq '') {
  225. print(" { NULL, 0 },\n");
  226. } else {
  227. my $num = '000' . $i;
  228. $num =~ s/\A.*?(\d\d\d)\Z/$1/;
  229. my $sym = "case_fold1_32_${num}";
  230. print(" { $sym, SDL_arraysize($sym) },\n");
  231. }
  232. $mem_used += 12;
  233. }
  234. print("};\n\n");
  235. print("static const CaseFoldHashBucket2_16 case_fold_hash2_16[] = {\n");
  236. for (my $i = 0; $i < $HASHBUCKETS2_16; $i++) {
  237. my $str = $foldPairs2_16[$i];
  238. if ($str eq '') {
  239. print(" { NULL, 0 },\n");
  240. } else {
  241. my $num = '000' . $i;
  242. $num =~ s/\A.*?(\d\d\d)\Z/$1/;
  243. my $sym = "case_fold2_16_${num}";
  244. print(" { $sym, SDL_arraysize($sym) },\n");
  245. }
  246. $mem_used += 12;
  247. }
  248. print("};\n\n");
  249. print("static const CaseFoldHashBucket3_16 case_fold_hash3_16[] = {\n");
  250. for (my $i = 0; $i < $HASHBUCKETS3_16; $i++) {
  251. my $str = $foldPairs3_16[$i];
  252. if ($str eq '') {
  253. print(" { NULL, 0 },\n");
  254. } else {
  255. my $num = '000' . $i;
  256. $num =~ s/\A.*?(\d\d\d)\Z/$1/;
  257. my $sym = "case_fold3_16_${num}";
  258. print(" { $sym, SDL_arraysize($sym) },\n");
  259. }
  260. $mem_used += 12;
  261. }
  262. print("};\n\n");
  263. print <<__EOF__;
  264. #endif /* SDL_casefolding_h_ */
  265. __EOF__
  266. print STDERR "Memory required for case-folding hashtable: $mem_used bytes\n";
  267. exit 0;
  268. # end of makecashfoldhashtable.pl ...