Normalize a wide-char path (faithful port of _Py_normpath_and_size). Uses lastC tracking like the C implementation.
(path: &[u16])
| 1579 | /// Normalize a wide-char path (faithful port of _Py_normpath_and_size). |
| 1580 | /// Uses lastC tracking like the C implementation. |
| 1581 | fn normpath_wide(path: &[u16]) -> Vec<u16> { |
| 1582 | if path.is_empty() { |
| 1583 | return vec![b'.' as u16]; |
| 1584 | } |
| 1585 | |
| 1586 | const SEP: u16 = b'\\' as u16; |
| 1587 | const ALTSEP: u16 = b'/' as u16; |
| 1588 | const DOT: u16 = b'.' as u16; |
| 1589 | |
| 1590 | let is_sep = |c: u16| c == SEP || c == ALTSEP; |
| 1591 | let sep_or_end = |input: &[u16], idx: usize| idx >= input.len() || is_sep(input[idx]); |
| 1592 | |
| 1593 | // Work on a mutable copy with normalized separators |
| 1594 | let mut buf: Vec<u16> = path |
| 1595 | .iter() |
| 1596 | .map(|&c| if c == ALTSEP { SEP } else { c }) |
| 1597 | .collect(); |
| 1598 | |
| 1599 | let (drv_size, root_size) = skiproot(&buf); |
| 1600 | let prefix_len = drv_size + root_size; |
| 1601 | |
| 1602 | // p1 = read cursor, p2 = write cursor |
| 1603 | let mut p1 = prefix_len; |
| 1604 | let mut p2 = prefix_len; |
| 1605 | let mut min_p2 = if prefix_len > 0 { prefix_len } else { 0 }; |
| 1606 | let mut last_c: u16 = if prefix_len > 0 { |
| 1607 | min_p2 = prefix_len - 1; |
| 1608 | let c = buf[min_p2]; |
| 1609 | // On Windows, if last char of prefix is not SEP, advance min_p2 |
| 1610 | if c != SEP { |
| 1611 | min_p2 = prefix_len; |
| 1612 | } |
| 1613 | c |
| 1614 | } else { |
| 1615 | 0 |
| 1616 | }; |
| 1617 | |
| 1618 | // Skip leading ".\" after prefix |
| 1619 | if p1 < buf.len() && buf[p1] == DOT && sep_or_end(&buf, p1 + 1) { |
| 1620 | p1 += 1; |
| 1621 | last_c = SEP; // treat as if we consumed a separator |
| 1622 | while p1 < buf.len() && buf[p1] == SEP { |
| 1623 | p1 += 1; |
| 1624 | } |
| 1625 | } |
| 1626 | |
| 1627 | while p1 < buf.len() { |
| 1628 | let c = buf[p1]; |
| 1629 | |
| 1630 | if last_c == SEP { |
| 1631 | if c == DOT { |
| 1632 | let sep_at_1 = sep_or_end(&buf, p1 + 1); |
| 1633 | let sep_at_2 = !sep_at_1 && sep_or_end(&buf, p1 + 2); |
| 1634 | if sep_at_2 && buf[p1 + 1] == DOT { |
| 1635 | // ".." component |
| 1636 | let mut p3 = p2; |
| 1637 | while p3 != min_p2 && buf[p3 - 1] == SEP { |
| 1638 | p3 -= 1; |