8262742: (fs) Add Path::resolve with varargs string
Reviewed-by: alanb
This commit is contained in:
parent
8008e27c55
commit
2bdfa836ad
src/java.base
test/jdk/java/nio/file/Path
@ -516,6 +516,90 @@ public interface Path
|
||||
return resolve(getFileSystem().getPath(other));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a path against this path, and then iteratively resolves any
|
||||
* additional paths.
|
||||
*
|
||||
* <p> This method resolves {@code first} against this {@code Path} as if
|
||||
* by calling {@link #resolve(Path)}. If {@code more} has one or more
|
||||
* elements then it resolves the first element against the result, then
|
||||
* iteratively resolves all subsequent elements. This method returns the
|
||||
* result from the final resolve.
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation is equivalent to the result obtained with:
|
||||
* {@snippet lang=java :
|
||||
* Path result = resolve(first);
|
||||
* for (Path p : more) {
|
||||
* result = result.resolve(p);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @param first
|
||||
* the first path to resolve against this path
|
||||
* @param more
|
||||
* additional paths to iteratively resolve
|
||||
*
|
||||
* @return the resulting path
|
||||
*
|
||||
* @see #resolve(Path)
|
||||
* @since 22
|
||||
*/
|
||||
default Path resolve(Path first, Path... more) {
|
||||
Path result = resolve(first);
|
||||
for (Path p : more) {
|
||||
result = result.resolve(p);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a path string to a path, resolves that path against this path,
|
||||
* and then iteratively performs the same procedure for any additional
|
||||
* path strings.
|
||||
*
|
||||
* <p> This method converts {@code first} to a {@code Path} and resolves
|
||||
* that {@code Path} against this {@code Path} as if by calling
|
||||
* {@link #resolve(String)}. If {@code more} has one or more elements
|
||||
* then it converts the first element to a path, resolves that path against
|
||||
* the result, then iteratively converts and resolves all subsequent
|
||||
* elements. This method returns the result from the final resolve.
|
||||
*
|
||||
* @implSpec
|
||||
* The default implementation is equivalent to the result obtained with:
|
||||
* {@snippet lang=java :
|
||||
* Path result = resolve(first);
|
||||
* for (String s : more) {
|
||||
* result = result.resolve(s);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @param first
|
||||
* the first path string to convert to a path and
|
||||
* resolve against this path
|
||||
*
|
||||
* @param more
|
||||
* additional path strings to be iteratively converted to
|
||||
* paths and resolved
|
||||
*
|
||||
* @return the resulting path
|
||||
*
|
||||
* @throws InvalidPathException
|
||||
* if a path string cannot be converted to a Path.
|
||||
*
|
||||
* @see #resolve(Path,Path...)
|
||||
* @see #resolve(String)
|
||||
*
|
||||
* @since 22
|
||||
*/
|
||||
default Path resolve(String first, String... more) {
|
||||
Path result = resolve(first);
|
||||
for (String s : more) {
|
||||
result = result.resolve(s);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the given path against this path's {@link #getParent parent}
|
||||
* path. This is useful where a file name needs to be <i>replaced</i> with
|
||||
|
@ -397,6 +397,83 @@ class UnixPath implements Path {
|
||||
return resolve(new UnixPath(getFileSystem(), other));
|
||||
}
|
||||
|
||||
private static final byte[] resolve(byte[] base, byte[]... children) {
|
||||
// 'start' is either zero, indicating the base, or indicates which
|
||||
// child is that last one which is an absolute path
|
||||
int start = 0;
|
||||
int resultLength = base.length;
|
||||
|
||||
// Locate the last child which is an absolute path and calculate
|
||||
// the total number of bytes in the resolved path
|
||||
final int count = children.length;
|
||||
if (count > 0) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
byte[] b = children[i];
|
||||
if (b.length > 0) {
|
||||
if (b[0] == '/') {
|
||||
start = i + 1;
|
||||
resultLength = b.length;
|
||||
} else {
|
||||
if (resultLength > 0)
|
||||
resultLength++;
|
||||
resultLength += b.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the base is not being superseded by a child which is an
|
||||
// absolute path, then if at least one child is non-empty and
|
||||
// the base consists only of a '/', then decrement resultLength to
|
||||
// account for an extra '/' added in the resultLength computation.
|
||||
if (start == 0 && resultLength > base.length && base.length == 1 && base[0] == '/')
|
||||
resultLength--;
|
||||
|
||||
// Allocate the result array and return if empty.
|
||||
byte[] result = new byte[resultLength];
|
||||
if (result.length == 0)
|
||||
return result;
|
||||
|
||||
// Prepend the base if it is non-empty and would not later be
|
||||
// overwritten by an absolute child
|
||||
int offset = 0;
|
||||
if (start == 0 && base.length > 0) {
|
||||
System.arraycopy(base, 0, result, 0, base.length);
|
||||
offset += base.length;
|
||||
}
|
||||
|
||||
// Append children starting with the last one which is an
|
||||
// absolute path
|
||||
if (count > 0) {
|
||||
int idx = Math.max(0, start - 1);
|
||||
for (int i = idx; i < count; i++) {
|
||||
byte[] b = children[i];
|
||||
if (b.length > 0) {
|
||||
if (offset > 0 && result[offset - 1] != '/')
|
||||
result[offset++] = '/';
|
||||
System.arraycopy(b, 0, result, offset, b.length);
|
||||
offset += b.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnixPath resolve(Path first, Path... more) {
|
||||
if (more.length == 0)
|
||||
return resolve(first);
|
||||
|
||||
byte[][] children = new byte[1 + more.length][];
|
||||
children[0] = toUnixPath(first).path;
|
||||
for (int i = 0; i < more.length; i++)
|
||||
children[i + 1] = toUnixPath(more[i]).path;
|
||||
|
||||
byte[] result = resolve(path, children);
|
||||
return new UnixPath(getFileSystem(), result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnixPath relativize(Path obj) {
|
||||
UnixPath child = toUnixPath(obj);
|
||||
|
@ -22,7 +22,8 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4313887 6838333 6925932 7006126 8037945 8072495 8140449 8254876 8298478
|
||||
* @bug 4313887 6838333 6925932 7006126 8037945 8072495 8140449 8254876 8262742
|
||||
* 8298478
|
||||
* @summary Unit test for java.nio.file.Path path operations
|
||||
*/
|
||||
|
||||
@ -182,6 +183,27 @@ public class PathOps {
|
||||
return this;
|
||||
}
|
||||
|
||||
// Note: "expected" is first parameter here
|
||||
PathOps resolve(String expected, String first, String... more) {
|
||||
out.format("test resolve %s varargs (String)\n", path());
|
||||
checkPath();
|
||||
check(path.resolve(first, more), expected);
|
||||
Path[] others = new Path[more.length];
|
||||
int i = 0;
|
||||
for (String s : more) {
|
||||
others[i++] = Path.of(s);
|
||||
}
|
||||
return resolve(expected, Path.of(first), others);
|
||||
}
|
||||
|
||||
// Note: "expected" is first parameter here
|
||||
PathOps resolve(String expected, Path first, Path... more) {
|
||||
out.format("test resolve %s varargs (Path)\n", path());
|
||||
checkPath();
|
||||
check(path.resolve(first, more), expected);
|
||||
return this;
|
||||
}
|
||||
|
||||
PathOps resolveSibling(String other, String expected) {
|
||||
out.format("test resolveSibling %s\n", other);
|
||||
checkPath();
|
||||
@ -543,6 +565,35 @@ public class PathOps {
|
||||
.resolve("C:foo", "C:foo")
|
||||
.resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar");
|
||||
|
||||
// resolve - varargs
|
||||
test("C:\\tmp")
|
||||
.resolve("C:\\tmp\\foo\\bar\\gus", "foo", "bar", "gus")
|
||||
.resolve("C:\\gus", "\\foo", "bar", "\\gus")
|
||||
.resolve("C:\\tmp\\baz", "", "", "baz");
|
||||
test("C:\\tmp\\foo")
|
||||
.resolve("C:\\tmp\\foo\\bar\\gus", "", "bar\\gus", "")
|
||||
.resolve("C:\\tmp\\foo\\bar\\gus\\foo\\baz",
|
||||
"", "bar\\gus", "foo\\baz")
|
||||
.resolve("C:\\bar\\gus\\baz", "", "C:\\bar\\gus", "baz")
|
||||
.resolve("C:\\tmp\\bar", "C:\\bar\\gus", "baz", "C:\\tmp\\bar");
|
||||
test("tmp")
|
||||
.resolve("tmp\\foo\\bar\\gus", "foo", "bar", "gus")
|
||||
.resolve("\\gus", "\\foo", "bar", "\\gus")
|
||||
.resolve("tmp\\baz", "", "", "baz");
|
||||
test("")
|
||||
.resolve("", "", "")
|
||||
.resolve("\\bar", "foo", "\\bar", "")
|
||||
.resolve("foo\\bar\\gus", "foo", "bar", "gus")
|
||||
.resolve("baz", "", "", "baz");
|
||||
test("\\")
|
||||
.resolve("\\foo", "foo", "")
|
||||
.resolve("\\foo", "", "foo")
|
||||
.resolve("\\bar", "foo", "", "\\bar");
|
||||
test("C:")
|
||||
.resolve("C:foo\\bar\\gus", "foo", "bar", "gus")
|
||||
.resolve("C:baz", "", "baz")
|
||||
.resolve("C:", "", "");
|
||||
|
||||
// resolveSibling
|
||||
test("foo")
|
||||
.resolveSibling("bar", "bar")
|
||||
@ -1669,6 +1720,31 @@ public class PathOps {
|
||||
.resolve("foo", "foo")
|
||||
.resolve("/foo", "/foo");
|
||||
|
||||
// resolve - varargs
|
||||
test("/tmp")
|
||||
.resolve("/tmp/foo/bar/gus", "foo", "bar", "gus")
|
||||
.resolve("/gus", "/foo", "bar", "/gus")
|
||||
.resolve("/tmp/baz", "", "", "baz");
|
||||
test("/tmp/foo")
|
||||
.resolve("/tmp/foo/bar/gus", "", "bar/gus", "")
|
||||
.resolve("/tmp/foo/bar/gus/foo/baz", "", "bar/gus", "foo/baz")
|
||||
.resolve("/bar/gus/baz", "", "/bar/gus", "baz")
|
||||
.resolve("/tmp/bar", "/bar/gus", "baz", "/tmp/bar");
|
||||
test("tmp")
|
||||
.resolve("tmp/foo/bar/gus", "foo", "bar", "gus")
|
||||
.resolve("/gus", "/foo", "bar", "/gus")
|
||||
.resolve("tmp/baz", "", "", "baz");
|
||||
test("")
|
||||
.resolve("", "", "")
|
||||
.resolve("/bar", "foo", "/bar", "")
|
||||
.resolve("foo/bar/gus", "foo", "bar", "gus")
|
||||
.resolve("baz", "", "", "baz");
|
||||
test("/")
|
||||
.resolve("/foo", "", "", "foo", "")
|
||||
.resolve("/foo", "foo", "")
|
||||
.resolve("/foo", "", "foo")
|
||||
.resolve("/bar", "foo", "", "/bar");
|
||||
|
||||
// resolveSibling
|
||||
test("foo")
|
||||
.resolveSibling("bar", "bar")
|
||||
@ -2077,7 +2153,7 @@ public class PathOps {
|
||||
}
|
||||
|
||||
try {
|
||||
Path.of("foo", null);
|
||||
Path.of("foo", (String[])null);
|
||||
throw new RuntimeException("NullPointerException not thrown");
|
||||
} catch (NullPointerException npe) {
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user