/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { posix, sep } from './path.js'; import { isWindows } from './platform.js'; import { startsWithIgnoreCase } from './strings.js'; export function isPathSeparator(code) { return code === 47 /* CharCode.Slash */ || code === 92 /* CharCode.Backslash */; } /** * Takes a Windows OS path and changes backward slashes to forward slashes. * This should only be done for OS paths from Windows (or user provided paths potentially from Windows). * Using it on a Linux or MaxOS path might change it. */ export function toSlashes(osPath) { return osPath.replace(/[\\/]/g, posix.sep); } /** * Takes a Windows OS path (using backward or forward slashes) and turns it into a posix path: * - turns backward slashes into forward slashes * - makes it absolute if it starts with a drive letter * This should only be done for OS paths from Windows (or user provided paths potentially from Windows). * Using it on a Linux or MaxOS path might change it. */ export function toPosixPath(osPath) { if (osPath.indexOf('/') === -1) { osPath = toSlashes(osPath); } if (/^[a-zA-Z]:(\/|$)/.test(osPath)) { // starts with a drive letter osPath = '/' + osPath; } return osPath; } /** * Computes the _root_ this path, like `getRoot('c:\files') === c:\`, * `getRoot('files:///files/path') === files:///`, * or `getRoot('\\server\shares\path') === \\server\shares\` */ export function getRoot(path, sep = posix.sep) { if (!path) { return ''; } const len = path.length; const firstLetter = path.charCodeAt(0); if (isPathSeparator(firstLetter)) { if (isPathSeparator(path.charCodeAt(1))) { // UNC candidate \\localhost\shares\ddd // ^^^^^^^^^^^^^^^^^^^ if (!isPathSeparator(path.charCodeAt(2))) { let pos = 3; const start = pos; for (; pos < len; pos++) { if (isPathSeparator(path.charCodeAt(pos))) { break; } } if (start !== pos && !isPathSeparator(path.charCodeAt(pos + 1))) { pos += 1; for (; pos < len; pos++) { if (isPathSeparator(path.charCodeAt(pos))) { return path.slice(0, pos + 1) // consume this separator .replace(/[\\/]/g, sep); } } } } } // /user/far // ^ return sep; } else if (isWindowsDriveLetter(firstLetter)) { // check for windows drive letter c:\ or c: if (path.charCodeAt(1) === 58 /* CharCode.Colon */) { if (isPathSeparator(path.charCodeAt(2))) { // C:\fff // ^^^ return path.slice(0, 2) + sep; } else { // C: // ^^ return path.slice(0, 2); } } } // check for URI // scheme://authority/path // ^^^^^^^^^^^^^^^^^^^ let pos = path.indexOf('://'); if (pos !== -1) { pos += 3; // 3 -> "://".length for (; pos < len; pos++) { if (isPathSeparator(path.charCodeAt(pos))) { return path.slice(0, pos + 1); // consume this separator } } } return ''; } /** * @deprecated please use `IUriIdentityService.extUri.isEqualOrParent` instead. If * you are in a context without services, consider to pass down the `extUri` from the * outside, or use `extUriBiasedIgnorePathCase` if you know what you are doing. */ export function isEqualOrParent(base, parentCandidate, ignoreCase, separator = sep) { if (base === parentCandidate) { return true; } if (!base || !parentCandidate) { return false; } if (parentCandidate.length > base.length) { return false; } if (ignoreCase) { const beginsWith = startsWithIgnoreCase(base, parentCandidate); if (!beginsWith) { return false; } if (parentCandidate.length === base.length) { return true; // same path, different casing } let sepOffset = parentCandidate.length; if (parentCandidate.charAt(parentCandidate.length - 1) === separator) { sepOffset--; // adjust the expected sep offset in case our candidate already ends in separator character } return base.charAt(sepOffset) === separator; } if (parentCandidate.charAt(parentCandidate.length - 1) !== separator) { parentCandidate += separator; } return base.indexOf(parentCandidate) === 0; } export function isWindowsDriveLetter(char0) { return char0 >= 65 /* CharCode.A */ && char0 <= 90 /* CharCode.Z */ || char0 >= 97 /* CharCode.a */ && char0 <= 122 /* CharCode.z */; } export function hasDriveLetter(path, isWindowsOS = isWindows) { if (isWindowsOS) { return isWindowsDriveLetter(path.charCodeAt(0)) && path.charCodeAt(1) === 58 /* CharCode.Colon */; } return false; }