Line data Source code
1 : // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 2 : // for details. All rights reserved. Use of this source code is governed by a 3 : // BSD-style license that can be found in the LICENSE file. 4 : 5 : import 'context.dart'; 6 : import 'style.dart'; 7 : 8 : /// The internal interface for the [Style] type. 9 : /// 10 : /// Users should be able to pass around instances of [Style] like an enum, but 11 : /// the members that [Context] uses should be hidden from them. Those members 12 : /// are defined on this class instead. 13 : abstract class InternalStyle extends Style { 14 : /// The default path separator for this style. 15 : /// 16 : /// On POSIX, this is `/`. On Windows, it's `\`. 17 : @override 18 : String get separator; 19 : 20 : /// Returns whether [path] contains a separator. 21 : bool containsSeparator(String path); 22 : 23 : /// Returns whether [codeUnit] is the character code of a separator. 24 : bool isSeparator(int codeUnit); 25 : 26 : /// Returns whether this path component needs a separator after it. 27 : /// 28 : /// Windows and POSIX styles just need separators when the previous component 29 : /// doesn't already end in a separator, but the URL always needs to place a 30 : /// separator between the root and the first component, even if the root 31 : /// already ends in a separator character. For example, to join "file://" and 32 : /// "usr", an additional "/" is needed (making "file:///usr"). 33 : bool needsSeparator(String path); 34 : 35 : /// Returns the number of characters of the root part. 36 : /// 37 : /// Returns 0 if the path is relative and 1 if the path is root-relative. 38 : /// 39 : /// If [withDrive] is `true`, this should include the drive letter for `file:` 40 : /// URLs. Non-URL styles may ignore the parameter. 41 : int rootLength(String path, {bool withDrive = false}); 42 : 43 : /// Gets the root prefix of [path] if path is absolute. If [path] is relative, 44 : /// returns `null`. 45 11 : @override 46 : String? getRoot(String path) { 47 11 : final length = rootLength(path); 48 22 : if (length > 0) return path.substring(0, length); 49 11 : return isRootRelative(path) ? path[0] : null; 50 : } 51 : 52 : /// Returns whether [path] is root-relative. 53 : /// 54 : /// If [path] is relative or absolute and not root-relative, returns `false`. 55 : bool isRootRelative(String path); 56 : 57 : /// Returns the path represented by [uri] in this style. 58 : @override 59 : String pathFromUri(Uri uri); 60 : 61 : /// Returns the URI that represents a relative path. 62 0 : @override 63 : Uri relativePathToUri(String path) { 64 0 : final segments = context.split(path); 65 : 66 : // Ensure that a trailing slash in the path produces a trailing slash in the 67 : // URL. 68 0 : if (isSeparator(path.codeUnitAt(path.length - 1))) segments.add(''); 69 0 : return Uri(pathSegments: segments); 70 : } 71 : 72 : /// Returns the URI that represents [path], which is assumed to be absolute. 73 : @override 74 : Uri absolutePathToUri(String path); 75 : 76 : /// Returns whether [codeUnit1] and [codeUnit2] are considered equivalent for 77 : /// this style. 78 0 : bool codeUnitsEqual(int codeUnit1, int codeUnit2) => codeUnit1 == codeUnit2; 79 : 80 : /// Returns whether [path1] and [path2] are equivalent. 81 : /// 82 : /// This only needs to handle character-by-character comparison; it can assume 83 : /// the paths are normalized and contain no `..` components. 84 22 : bool pathsEqual(String path1, String path2) => path1 == path2; 85 : 86 0 : int canonicalizeCodeUnit(int codeUnit) => codeUnit; 87 : 88 0 : String canonicalizePart(String part) => part; 89 : }