/** * Constructs a GlobDescriptor. * * @param packageId the name of the owner package (must be an existing package) * @param subdir the subdirectory being looked at (must exist and must be a directory. It's * assumed that there are no other packages between {@code packageName} and {@code subdir}. * @param pattern a valid glob pattern * @param excludeDirs true if directories should be excluded from results */ GlobDescriptor( PackageIdentifier packageId, PathFragment subdir, String pattern, boolean excludeDirs) { this.packageId = Preconditions.checkNotNull(packageId); this.subdir = Preconditions.checkNotNull(subdir); this.pattern = Preconditions.checkNotNull(StringCanonicalizer.intern(pattern)); this.excludeDirs = excludeDirs; }
/** * Returns the path formed by appending the single non-special segment "baseName" to this path. * * <p>You should almost always use {@link #getRelative} instead, which has the same performance * characteristics if the given name is a valid base name, and which also works for '.', '..', and * strings containing '/'. * * @throws IllegalArgumentException if {@code baseName} is not a valid base name according to * {@link FileSystemUtils#checkBaseName} */ public PathFragment getChild(String baseName) { FileSystemUtils.checkBaseName(baseName); baseName = StringCanonicalizer.intern(baseName); String[] newSegments = Arrays.copyOf(segments, segments.length + 1); newSegments[newSegments.length - 1] = baseName; return new PathFragment(driveLetter, isAbsolute, newSegments); }
/** Lower-level API. Create a PathFragment, interning segments. */ public static PathFragment create(char driveLetter, boolean isAbsolute, String[] segments) { String[] internedSegments = new String[segments.length]; for (int i = 0; i < segments.length; i++) { internedSegments[i] = StringCanonicalizer.intern(segments[i]); } return new PathFragment(driveLetter, isAbsolute, segments); }
/** * Segments the string passed in as argument and returns an array of strings. The split is * performed along occurrences of (sequences of) the slash character. * * @param toSegment the string to segment * @param offset how many characters from the start of the string to ignore. */ private static String[] segment(String toSegment, int offset) { char[] chars = toSegment.toCharArray(); int length = chars.length; // Handle "/" and "" quickly. if (length == offset) { return new String[0]; } // We make two passes through the array of characters: count & alloc, // because simply using ArrayList was a bottleneck showing up during profiling. int seg = 0; int start = offset; for (int i = offset; i < length; i++) { if (isSeparator(chars[i])) { if (i > start) { // to skip repeated separators seg++; } start = i + 1; } } if (start < length) { seg++; } String[] result = new String[seg]; seg = 0; start = offset; for (int i = offset; i < length; i++) { if (isSeparator(chars[i])) { if (i > start) { // to skip repeated separators // Make a copy of the String here to allow the interning to save memory. String.substring // does not make a copy, but refers to the original char array, preventing garbage // collection of the parts that are unnecessary. result[seg] = StringCanonicalizer.intern(new String(chars, start, i - start)); seg++; } start = i + 1; } } if (start < length) { result[seg] = StringCanonicalizer.intern(new String(chars, start, length - start)); seg++; } return result; }
/** * Makes sure that name is a valid repository name and creates a new RepositoryName using it. * * @throws SyntaxException if the name is invalid. */ public static RepositoryName create(String name) throws SyntaxException { String errorMessage = validate(name); if (errorMessage != null) { errorMessage = "invalid repository name '" + StringUtilities.sanitizeControlChars(name) + "': " + errorMessage; throw new SyntaxException(errorMessage); } return new RepositoryName(StringCanonicalizer.intern(name)); }
/** * Returns the path string using '/' as the name-separator character. Returns "" if the path is * both relative and empty. */ public String getPathString() { // Double-checked locking works, even without volatile, because path is a String, according to: // http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html if (path == null) { synchronized (this) { if (path == null) { path = StringCanonicalizer.intern(joinSegments(SEPARATOR_CHAR)); } } } return path; }