We convert the file names to lower case as key for file name on case insensitive file system While doing so we need to handle special characters (eg \u0130) to ensure that we dont convert it to lower case, fileName with its lowercase form can exist along side it. Handle special characters and make t
(fileName string)
| 636 | // they have corresponding upper case character so they dont need special handling |
| 637 | |
| 638 | func ToFileNameLowerCase(fileName string) string { |
| 639 | const IWithDot = '\u0130' |
| 640 | |
| 641 | ascii := true |
| 642 | needsLower := false |
| 643 | fileNameLen := len(fileName) |
| 644 | for i := range fileNameLen { |
| 645 | c := fileName[i] |
| 646 | if c >= 0x80 { |
| 647 | ascii = false |
| 648 | break |
| 649 | } |
| 650 | if 'A' <= c && c <= 'Z' { |
| 651 | needsLower = true |
| 652 | } |
| 653 | } |
| 654 | if ascii { |
| 655 | if !needsLower { |
| 656 | return fileName |
| 657 | } |
| 658 | b := make([]byte, fileNameLen) |
| 659 | for i := range fileNameLen { |
| 660 | c := fileName[i] |
| 661 | if 'A' <= c && c <= 'Z' { |
| 662 | c += 'a' - 'A' // +32 |
| 663 | } |
| 664 | b[i] = c |
| 665 | } |
| 666 | // SAFETY: We construct a string that aliases b’s backing array without copying. |
| 667 | // (1) Lifetime: The address of b’s elements escapes via the returned string, |
| 668 | // so escape analysis allocates b’s backing array on the heap. The string |
| 669 | // header points to that heap allocation, ensuring it remains live for the |
| 670 | // string’s lifetime. |
| 671 | // (2) Initialization: We assign to every b[i] before creating the string. |
| 672 | // (Note: Go zeroes all allocated memory, so “uninitialized” bytes cannot occur.) |
| 673 | // (3) Immutability: We do not modify b after this point, so the string view |
| 674 | // observes immutable data. |
| 675 | // (4) Non-empty: On this path len(b) > 0, so &b[0] is a valid, non-nil pointer. |
| 676 | return unsafe.String(&b[0], len(b)) |
| 677 | } |
| 678 | |
| 679 | return strings.Map(func(r rune) rune { |
| 680 | if r == IWithDot { |
| 681 | return r |
| 682 | } |
| 683 | return unicode.ToLower(r) |
| 684 | }, fileName) |
| 685 | } |
| 686 | |
| 687 | func ToPath(fileName string, basePath string, useCaseSensitiveFileNames bool) Path { |
| 688 | var nonCanonicalizedPath string |