DarkShadow44

Untitled

May 1st, 2020
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.69 KB | None | 0 0
  1. #define SORTKEY_UNSORTABLE 0
  2. #define SORTKEY_DIACRITIC 1
  3. #define SORTKEY_JAPANESE 3
  4. #define SORTKEY_JAMO 4
  5. #define SORTKEY_EXTENSION 5
  6. #define SORTKEY_PUNCTUATION 6
  7. #define SORTKEY_SYMBOL_1 7
  8. #define SORTKEY_SYMBOL_2 8
  9. #define SORTKEY_SYMBOL_3 9
  10. #define SORTKEY_SYMBOL_4 10
  11. #define SORTKEY_SYMBOL_5 11
  12. #define SORTKEY_SYMBOL_6 12
  13.  
  14. #define SORTKEY_MIN_WEIGHT 2
  15.  
  16. enum sortkey_weight_type
  17. {
  18. SORTKEY_WEIGHT_TYPE_SEPARATOR,
  19. SORTKEY_WEIGHT_TYPE_MAIN,
  20. SORTKEY_WEIGHT_TYPE_DIACRITIC,
  21. SORTKEY_WEIGHT_TYPE_CASE,
  22. SORTKEY_WEIGHT_TYPE_EXTRA,
  23. SORTKEY_WEIGHT_TYPE_SPECIAL,
  24. };
  25.  
  26. struct character_info
  27. {
  28. BYTE weight_primary;
  29. BYTE script_member;
  30. BYTE weight_diacritic;
  31. BYTE weight_case;
  32. };
  33.  
  34. struct weight_main_info
  35. {
  36. BYTE script_member;
  37. BYTE weight_primary;
  38. BYTE extra;
  39. };
  40.  
  41. struct sortkey_data
  42. {
  43. int flags;
  44. BYTE* buffer;
  45. int buffer_pos;
  46. int buffer_len;
  47. enum sortkey_weight_type weight_type;
  48. int pos_last_weight_bigger_min;
  49. };
  50.  
  51. static BOOL sortkey_get_char(struct sortkey_data* data, struct character_info* info, WCHAR ch)
  52. {
  53. DWORD value = sort.keys[ch];
  54.  
  55. info->weight_case = value >> 24;
  56. info->weight_diacritic = (value >> 16) & 0xff;
  57. info->script_member = (value >> 8) & 0xff;
  58. info->weight_primary = value & 0xff;
  59. return info->script_member != 0;
  60. }
  61.  
  62. static void sortkey_data_init(struct sortkey_data* data, BYTE* buffer, int buffer_len, int flags, const WCHAR* locale, BOOL is_compare_string)
  63. {
  64. data->flags = flags;
  65. data->buffer = buffer;
  66. data->buffer_pos = 0;
  67. data->buffer_len = buffer ? buffer_len : 0;
  68. }
  69.  
  70. static struct weight_main_info sortkey_create_weight_main(BYTE script_member, BYTE weight_primary)
  71. {
  72. struct weight_main_info ret = { 0 };
  73. ret.script_member = script_member;
  74. ret.weight_primary = weight_primary;
  75. return ret;
  76. }
  77.  
  78. static void sortkey_add_weight(struct sortkey_data* data, enum sortkey_weight_type weight_type, BYTE value)
  79. {
  80. if (weight_type != SORTKEY_WEIGHT_TYPE_SEPARATOR && data->weight_type != weight_type)
  81. return;
  82. if (data->buffer_pos < data->buffer_len)
  83. data->buffer[data->buffer_pos] = value;
  84. data->buffer_pos++;
  85. }
  86.  
  87. static void sortkey_case_weights_add(struct sortkey_data* data, BYTE value)
  88. {
  89. int flags = data->flags;
  90. if (NORM_IGNORECASE & flags)
  91. value = value & ~(16 + 8);
  92. if (NORM_IGNOREWIDTH & flags)
  93. value = value & ~(1);
  94. if (NORM_IGNOREKANATYPE & flags)
  95. value = value & ~(32);
  96.  
  97. sortkey_add_weight(data, SORTKEY_WEIGHT_TYPE_CASE, value);
  98. }
  99.  
  100. static void sortkey_main_weights_add(struct sortkey_data *data, struct weight_main_info* value)
  101. {
  102. sortkey_add_weight(data, SORTKEY_WEIGHT_TYPE_MAIN, value->script_member);
  103. sortkey_add_weight(data, SORTKEY_WEIGHT_TYPE_MAIN, value->weight_primary);
  104. if (value->extra > 0)
  105. sortkey_add_weight(data, SORTKEY_WEIGHT_TYPE_MAIN, value->extra);
  106. }
  107.  
  108. static void sortkey_diacritic_weights_add(struct sortkey_data* data, const struct character_info* info, BYTE value)
  109. {
  110. sortkey_add_weight(data, SORTKEY_WEIGHT_TYPE_DIACRITIC, value);
  111. if (value > SORTKEY_MIN_WEIGHT)
  112. data->pos_last_weight_bigger_min = data->buffer_pos;
  113. }
  114.  
  115. static void sortkey_handle_default_character(struct sortkey_data* data, WCHAR c)
  116. {
  117. struct weight_main_info weightmain;
  118. struct character_info info;
  119.  
  120. if (!sortkey_get_char(data, &info, c))
  121. {
  122. return;
  123. }
  124.  
  125. weightmain = sortkey_create_weight_main(info.script_member, info.weight_primary);
  126. if (info.script_member >= 0xa9 && info.script_member <= 0xaf) /* Some CJK have extra value */
  127. weightmain.extra = info.weight_diacritic;
  128. else
  129. sortkey_diacritic_weights_add(data, &info, info.weight_diacritic);
  130.  
  131. sortkey_main_weights_add(data, &weightmain);
  132.  
  133. sortkey_case_weights_add(data, info.weight_case);
  134. }
  135.  
  136. static BOOL sortkey_handle_character(struct sortkey_data* data, WCHAR c, const WCHAR* str, int i)
  137. {
  138. struct weight_main_info weightmain;
  139. struct character_info info;
  140. int flags = data->flags;
  141.  
  142. if (!sortkey_get_char(data, &info, c))
  143. {
  144. return FALSE;
  145. }
  146.  
  147. switch (info.script_member)
  148. {
  149. case SORTKEY_UNSORTABLE:
  150. break;
  151.  
  152. case SORTKEY_DIACRITIC:
  153. if (data->weight_type == SORTKEY_WEIGHT_TYPE_DIACRITIC)
  154. {
  155. int old_pos = data->buffer_pos - 1;
  156. if (old_pos >= 0 && old_pos < data->buffer_len)
  157. data->buffer[old_pos] += info.weight_diacritic; /* Overflow can happen, that's okay */
  158. else
  159. sortkey_diacritic_weights_add(data, &info, info.weight_diacritic);
  160. }
  161. break;
  162.  
  163. case SORTKEY_JAPANESE:
  164. /* TODO */
  165. break;
  166.  
  167. case SORTKEY_JAMO:
  168. weightmain = sortkey_create_weight_main(info.weight_primary, info.weight_diacritic);
  169. sortkey_main_weights_add(data, &weightmain);
  170.  
  171. sortkey_diacritic_weights_add(data, &info, SORTKEY_MIN_WEIGHT);
  172.  
  173. sortkey_case_weights_add(data, info.weight_case);
  174. break;
  175.  
  176. case SORTKEY_EXTENSION:
  177. weightmain = sortkey_create_weight_main(253, 255);
  178. sortkey_main_weights_add(data, &weightmain);
  179.  
  180. weightmain = sortkey_create_weight_main(info.weight_primary, info.weight_diacritic);
  181. sortkey_main_weights_add(data, &weightmain);
  182.  
  183. sortkey_diacritic_weights_add(data, &info, SORTKEY_MIN_WEIGHT);
  184.  
  185. sortkey_case_weights_add(data, SORTKEY_MIN_WEIGHT);
  186. break;
  187.  
  188. case SORTKEY_PUNCTUATION:
  189. /* TODO */
  190. break;
  191.  
  192. case SORTKEY_SYMBOL_1:
  193. case SORTKEY_SYMBOL_2:
  194. case SORTKEY_SYMBOL_3:
  195. case SORTKEY_SYMBOL_4:
  196. case SORTKEY_SYMBOL_5:
  197. case SORTKEY_SYMBOL_6:
  198. if (flags & NORM_IGNORESYMBOLS)
  199. break;
  200.  
  201. weightmain = sortkey_create_weight_main(info.script_member, info.weight_primary);
  202. sortkey_main_weights_add(data, &weightmain);
  203.  
  204. sortkey_diacritic_weights_add(data, &info, info.weight_diacritic);
  205.  
  206. sortkey_case_weights_add(data, info.weight_case);
  207. break;
  208.  
  209. default:
  210. sortkey_handle_default_character(data, c);
  211. break;
  212. }
  213. return TRUE;
  214. }
  215.  
  216. static void sortkey_start_weight(struct sortkey_data* data, enum sortkey_weight_type weight_type)
  217. {
  218. data->buffer += data->buffer_pos;
  219. data->buffer_len -= data->buffer_pos;
  220. data->buffer_pos = 0;
  221. data->weight_type = weight_type;
  222. data->pos_last_weight_bigger_min = 0;
  223. }
  224.  
  225. static int sortkey_generate(int flags, const WCHAR* locale, const WCHAR* str, int str_len, BYTE* buffer, int buffer_len)
  226. {
  227. const BYTE SORTKEY_SEPARATOR = 1;
  228. const BYTE SORTKEY_TERMINATOR = 0;
  229. int i;
  230. struct sortkey_data data;
  231. int sortkey_len = 0;
  232.  
  233. sortkey_data_init(&data, buffer, buffer_len, flags, locale, FALSE);
  234.  
  235. if (str_len == -1)
  236. str_len = wcslen(str);
  237.  
  238. /* Main weights */
  239. sortkey_start_weight(&data, SORTKEY_WEIGHT_TYPE_MAIN);
  240. for (i = 0; i < str_len; i++)
  241. sortkey_handle_character(&data, str[i], str, i);
  242. sortkey_add_weight(&data, SORTKEY_WEIGHT_TYPE_SEPARATOR, SORTKEY_SEPARATOR);
  243. sortkey_len += data.buffer_pos;
  244.  
  245. /* Diacritic weights */
  246. sortkey_start_weight(&data, SORTKEY_WEIGHT_TYPE_DIACRITIC);
  247. if ((flags & NORM_IGNORENONSPACE) == 0)
  248. {
  249. for (i = 0; i < str_len; i++)
  250. sortkey_handle_character(&data, str[i], str, i);
  251. /* Remove all weights <= SORTKEY_MIN_WEIGHT from the end */
  252. data.buffer_pos = data.pos_last_weight_bigger_min;
  253. }
  254. sortkey_add_weight(&data, SORTKEY_WEIGHT_TYPE_SEPARATOR, SORTKEY_SEPARATOR);
  255. sortkey_len += data.buffer_pos;
  256.  
  257. /* Case weights */
  258. sortkey_start_weight(&data, SORTKEY_WEIGHT_TYPE_CASE);
  259. if ((NORM_IGNORECASE & flags) == 0 || (NORM_IGNOREWIDTH & flags) == 0)
  260. {
  261. for (i = 0; i < str_len; i++)
  262. sortkey_handle_character(&data, str[i], str, i);
  263. }
  264. sortkey_add_weight(&data, SORTKEY_WEIGHT_TYPE_SEPARATOR, SORTKEY_SEPARATOR);
  265. sortkey_len += data.buffer_pos;
  266.  
  267. /* Extra weights */
  268. sortkey_start_weight(&data, SORTKEY_WEIGHT_TYPE_EXTRA);
  269. /* TODO */
  270. sortkey_add_weight(&data, SORTKEY_WEIGHT_TYPE_SEPARATOR, SORTKEY_SEPARATOR);
  271. sortkey_len += data.buffer_pos;
  272.  
  273. /* Special weights */
  274. sortkey_start_weight(&data, SORTKEY_WEIGHT_TYPE_SPECIAL);
  275. /* TODO */
  276. sortkey_add_weight(&data, SORTKEY_WEIGHT_TYPE_SEPARATOR, SORTKEY_TERMINATOR);
  277. sortkey_len += data.buffer_pos;
  278.  
  279. if (sortkey_len <= buffer_len || !buffer)
  280. return sortkey_len;
  281.  
  282. return 0;
  283. }
Advertisement
Add Comment
Please, Sign In to add comment