2 #include "physfs_internal.h" |
2 #include "physfs_internal.h" |
3 |
3 |
4 |
4 |
5 /* |
5 /* |
6 * From rfc3629, the UTF-8 spec: |
6 * From rfc3629, the UTF-8 spec: |
7 * http://www.ietf.org/rfc/rfc3629.txt |
7 * https://www.ietf.org/rfc/rfc3629.txt |
8 * |
8 * |
9 * Char. number range | UTF-8 octet sequence |
9 * Char. number range | UTF-8 octet sequence |
10 * (hexadecimal) | (binary) |
10 * (hexadecimal) | (binary) |
11 * --------------------+--------------------------------------------- |
11 * --------------------+--------------------------------------------- |
12 * 0000 0000-0000 007F | 0xxxxxxx |
12 * 0000 0000-0000 007F | 0xxxxxxx |
445 |
445 |
446 |
446 |
447 static int utf8codepointcmp(const PHYSFS_uint32 cp1, const PHYSFS_uint32 cp2) |
447 static int utf8codepointcmp(const PHYSFS_uint32 cp1, const PHYSFS_uint32 cp2) |
448 { |
448 { |
449 PHYSFS_uint32 folded1[3], folded2[3]; |
449 PHYSFS_uint32 folded1[3], folded2[3]; |
|
450 |
|
451 if (cp1 == cp2) |
|
452 return 0; /* obviously matches. */ |
|
453 |
450 locate_case_fold_mapping(cp1, folded1); |
454 locate_case_fold_mapping(cp1, folded1); |
451 locate_case_fold_mapping(cp2, folded2); |
455 locate_case_fold_mapping(cp2, folded2); |
452 return ( (folded1[0] == folded2[0]) && |
456 |
453 (folded1[1] == folded2[1]) && |
457 if (folded1[0] < folded2[0]) |
454 (folded1[2] == folded2[2]) ); |
458 return -1; |
|
459 else if (folded1[0] > folded2[0]) |
|
460 return 1; |
|
461 else if (folded1[1] < folded2[1]) |
|
462 return -1; |
|
463 else if (folded1[1] > folded2[1]) |
|
464 return 1; |
|
465 else if (folded1[2] < folded2[2]) |
|
466 return -1; |
|
467 else if (folded1[2] > folded2[2]) |
|
468 return 1; |
|
469 |
|
470 return 0; /* complete match. */ |
455 } /* utf8codepointcmp */ |
471 } /* utf8codepointcmp */ |
456 |
472 |
457 |
473 |
458 int __PHYSFS_utf8stricmp(const char *str1, const char *str2) |
474 int __PHYSFS_utf8stricmp(const char *str1, const char *str2) |
459 { |
475 { |
460 while (1) |
476 while (1) |
461 { |
477 { |
462 const PHYSFS_uint32 cp1 = utf8codepoint(&str1); |
478 const PHYSFS_uint32 cp1 = utf8codepoint(&str1); |
463 const PHYSFS_uint32 cp2 = utf8codepoint(&str2); |
479 const PHYSFS_uint32 cp2 = utf8codepoint(&str2); |
464 if (!utf8codepointcmp(cp1, cp2)) break; |
480 const int rc = utf8codepointcmp(cp1, cp2); |
465 if (cp1 == 0) return 1; |
481 if (rc != 0) |
|
482 return rc; |
|
483 else if (cp1 == 0) |
|
484 break; /* complete match. */ |
466 } /* while */ |
485 } /* while */ |
467 |
486 |
468 return 0; |
487 return 0; |
469 } /* __PHYSFS_utf8stricmp */ |
488 } /* __PHYSFS_utf8stricmp */ |
470 |
489 |
473 { |
492 { |
474 while (n > 0) |
493 while (n > 0) |
475 { |
494 { |
476 const PHYSFS_uint32 cp1 = utf8codepoint(&str1); |
495 const PHYSFS_uint32 cp1 = utf8codepoint(&str1); |
477 const PHYSFS_uint32 cp2 = utf8codepoint(&str2); |
496 const PHYSFS_uint32 cp2 = utf8codepoint(&str2); |
478 if (!utf8codepointcmp(cp1, cp2)) return 0; |
497 const int rc = utf8codepointcmp(cp1, cp2); |
479 if (cp1 == 0) return 1; |
498 if (rc != 0) |
|
499 return rc; |
|
500 else if (cp1 == 0) |
|
501 return 0; |
480 n--; |
502 n--; |
481 } /* while */ |
503 } /* while */ |
482 |
504 |
483 return 1; /* matched to n chars. */ |
505 return 0; /* matched to n chars. */ |
484 } /* __PHYSFS_utf8strnicmp */ |
506 } /* __PHYSFS_utf8strnicmp */ |
485 |
507 |
486 |
508 |
487 int __PHYSFS_stricmpASCII(const char *str1, const char *str2) |
509 int __PHYSFS_stricmpASCII(const char *str1, const char *str2) |
488 { |
510 { |