/*******************************************************************************
 * Copyright (c) 2000, 2015 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Patrick Tasse - Add extra constructor to Path class (bug 454959)
 *******************************************************************************/
package org.eclipse.core.runtime;

import java.io.File;
import java.util.Arrays;

/** 
 * The standard implementation of the <code>IPath</code> interface.
 * Paths are always maintained in canonicalized form.  That is, parent
 * references (i.e., <code>../../</code>) and duplicate separators are 
 * resolved.  For example,
 * <pre>     new Path("/a/b").append("../foo/bar")</pre>
 * will yield the path
 * <pre>     /a/foo/bar</pre>
 * <p>
 * This class can be used without OSGi running.
 * </p><p>
 * This class is not intended to be subclassed by clients but
 * may be instantiated.
 * </p>
 * @see IPath
 * @noextend This class is not intended to be subclassed by clients.
 */
public class Path implements IPath, Cloneable {
	/** masks for flag values */
	private static final int HAS_LEADING = 1;
	private static final int IS_UNC = 2;
	private static final int HAS_TRAILING = 4;
	private static final int IS_FOR_WINDOWS = 8;

	private static final int ALL_SEPARATORS = HAS_LEADING | IS_UNC | HAS_TRAILING;
	private static final int ALL_FLAGS = HAS_LEADING | IS_UNC | HAS_TRAILING | IS_FOR_WINDOWS;

	/** Constant value indicating if the current platform is Windows */
	private static final boolean RUNNING_ON_WINDOWS = java.io.File.separatorChar == '\\';

	/** Constant empty string value. */
	private static final String EMPTY_STRING = ""; //$NON-NLS-1$

	/** Constant value indicating no segments */
	private static final String[] NO_SEGMENTS = new String[0];

	/** Constant value containing the empty path with no device on the local file system. */
	public static final Path EMPTY = new Path(EMPTY_STRING);

	/** Mask for all bits that are involved in the hash code */
	private static final int HASH_MASK = ~(HAS_TRAILING | IS_FOR_WINDOWS);

	/** Constant root path string (<code>"/"</code>). */
	private static final String ROOT_STRING = "/"; //$NON-NLS-1$

	/** Constant value containing the root path with no device on the local file system. */
	public static final Path ROOT = new Path(ROOT_STRING);

	/** The device id string. May be null if there is no device. */
	private String device = null;

	//Private implementation note: the segments array and flag bitmap
	//are never modified, so that they can be shared between path instances

	/** The path segments */
	private String[] segments;

	/** flags indicating separators (has leading, is UNC, has trailing, is for Windows) */
	private int flags;

	/** 
	 * Constructs a new path from the given string path.
	 * The string path must represent a valid file system path
	 * on the local file system. 
	 * The path is canonicalized and double slashes are removed
	 * except at the beginning. (to handle UNC paths). All forward
	 * slashes ('/') are treated as segment delimiters, and any
	 * segment and device delimiters for the local file system are
	 * also respected.
	 *
	 * @param pathString the portable string path
	 * @see IPath#toPortableString()
	 * @since 3.1
	 */
	public static IPath fromOSString(String pathString) {
		return new Path(pathString);
	}

	/** 
	 * Constructs a new path from the given path string.
	 * The path string must have been produced by a previous
	 * call to <code>IPath.toPortableString</code>.
	 *
	 * @param pathString the portable path string
	 * @see IPath#toPortableString()
	 * @since 3.1
	 */
	public static IPath fromPortableString(String pathString) {
		int firstMatch = pathString.indexOf(DEVICE_SEPARATOR) + 1;
		//no extra work required if no device characters
		if (firstMatch <= 0)
			return new Path().initialize(null, pathString, RUNNING_ON_WINDOWS);
		//if we find a single colon, then the path has a device
		String devicePart = null;
		int pathLength = pathString.length();
		if (firstMatch == pathLength || pathString.charAt(firstMatch) != DEVICE_SEPARATOR) {
			devicePart = pathString.substring(0, firstMatch);
			pathString = pathString.substring(firstMatch, pathLength);
		}
		//optimize for no colon literals
		if (pathString.indexOf(DEVICE_SEPARATOR) == -1)
			return new Path().initialize(devicePart, pathString, RUNNING_ON_WINDOWS);
		//contract colon literals
		char[] chars = pathString.toCharArray();
		int readOffset = 0, writeOffset = 0, length = chars.length;
		while (readOffset < length) {
			if (chars[readOffset] == DEVICE_SEPARATOR)
				if (++readOffset >= length)
					break;
			chars[writeOffset++] = chars[readOffset++];
		}
		return new Path().initialize(devicePart, new String(chars, 0, writeOffset), RUNNING_ON_WINDOWS);
	}

	/**
	 * Constructs a new POSIX path from the given string path. The string path
	 * must represent a valid file system path on a POSIX file system. The path
	 * is canonicalized and double slashes are removed except at the beginning
	 * (to handle UNC paths). All forward slashes ('/') are treated as segment
	 * delimiters. This factory method should be used if the string path is for
	 * a POSIX file system.
	 *
	 * @param fullPath the string path
	 * @see #isValidPosixPath(String)
	 * @since 3.7
	 */
	public static Path forPosix(String fullPath) {
		return new Path(fullPath, false);
	}

	/**
	 * Constructs a new Windows path from the given string path. The string path
	 * must represent a valid file system path on the Windows file system. The
	 * path is canonicalized and double slashes are removed except at the
	 * beginning (to handle UNC paths). All forward slashes ('/') are treated as
	 * segment delimiters, and any segment ('\') and device (':') delimiters for
	 * the Windows file system are also respected. This factory method should be
	 * used if the string path is for the Windows file system.
	 *
	 * @param fullPath the string path
	 * @see #isValidWindowsPath(String)
	 * @since 3.7
	 */
	public static Path forWindows(String fullPath) {
		return new Path(fullPath, true);
	}

	/* (Intentionally not included in javadoc)
	 * Private constructor.
	 */
	private Path() {
		// not allowed
	}

	/** 
	 * Constructs a new path from the given string path.
	 * The string path must represent a valid file system path
	 * on the local file system. 
	 * The path is canonicalized and double slashes are removed
	 * except at the beginning. (to handle UNC paths). All forward
	 * slashes ('/') are treated as segment delimiters, and any
	 * segment and device delimiters for the local file system are
	 * also respected (such as colon (':') and backslash ('\') on some file systems).
	 * This constructor should be used if the string path if for the local file system.
	 *
	 * @param fullPath the string path
	 * @see #isValidPath(String)
	 */
	public Path(String fullPath) {
		this(fullPath, RUNNING_ON_WINDOWS);
	}

	/** 
	 * Constructs a new path from the given device id and string path.
	 * The given string path must be valid.
	 * The path is canonicalized and double slashes are removed except
	 * at the beginning (to handle UNC paths). All forward
	 * slashes ('/') are treated as segment delimiters, and any
	 * segment delimiters for the local file system are
	 * also respected (such as backslash ('\') on some file systems).
	 *
	 * @param device the device id
	 * @param path the string path
	 * @see #isValidPath(String)
	 * @see #setDevice(String)
	 */
	public Path(String device, String path) {
		if (RUNNING_ON_WINDOWS) {
			//convert backslash to forward slash
			path = path.indexOf('\\') == -1 ? path : path.replace('\\', SEPARATOR);
		}
		initialize(device, path, RUNNING_ON_WINDOWS);
	}

	/** 
	 * Constructs a new path from the given string path. The string path must
	 * represent a valid file system path on the specified file system. The path
	 * is canonicalized and double slashes are removed except at the beginning
	 * (to handle UNC paths). All forward slashes ('/') are treated as segment
	 * delimiters, and any segment and device delimiters for the specified file
	 * system are also respected (such as colon (':') and backslash ('\') on
	 * Windows).
	 *
	 * @param fullPath the string path
	 * @param forWindows true if the string path is for the Windows file system
	 * @since 3.7
	 */
	private Path(String fullPath, boolean forWindows) {
		String devicePart = null;
		if (forWindows) {
			//convert backslash to forward slash
			fullPath = fullPath.indexOf('\\') == -1 ? fullPath : fullPath.replace('\\', SEPARATOR);
			//extract device
			int i = fullPath.indexOf(DEVICE_SEPARATOR);
			if (i != -1) {
				//remove leading slash from device part to handle output of URL.getFile()
				int start = fullPath.charAt(0) == SEPARATOR ? 1 : 0;
				devicePart = fullPath.substring(start, i + 1);
				fullPath = fullPath.substring(i + 1, fullPath.length());
			}
		}
		initialize(devicePart, fullPath, forWindows);
	}

	/* (Intentionally not included in javadoc)
	 * Private constructor.
	 */
	private Path(String device, String[] segments, int flags) {
		// no segment validations are done for performance reasons	
		this.segments = segments;
		this.device = device;
		//hash code is cached in all but the bottom four bits of the flags field
		this.flags = (computeHashCode() << 4) | (flags & ALL_FLAGS);
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#addFileExtension
	 */
	@Override
	public IPath addFileExtension(String extension) {
		if (isRoot() || isEmpty() || hasTrailingSeparator())
			return this;
		int len = segments.length;
		String[] newSegments = new String[len];
		System.arraycopy(segments, 0, newSegments, 0, len - 1);
		newSegments[len - 1] = segments[len - 1] + '.' + extension;
		return new Path(device, newSegments, flags);
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#addTrailingSeparator
	 */
	@Override
	public IPath addTrailingSeparator() {
		if (hasTrailingSeparator() || isRoot()) {
			return this;
		}
		//XXX workaround, see 1GIGQ9V
		if (isEmpty()) {
			return new Path(device, segments, (flags & IS_FOR_WINDOWS) | HAS_LEADING);
		}
		return new Path(device, segments, flags | HAS_TRAILING);
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#append(IPath)
	 */
	@Override
	public IPath append(IPath tail) {
		//optimize some easy cases
		if (tail == null || tail.segmentCount() == 0)
			return this;
		//these call chains look expensive, but in most cases they are no-ops
		//the tail must be for the same platform as this instance
		if (this.isEmpty() && ((flags & IS_FOR_WINDOWS) == 0) == tail.isValidSegment(":")) //$NON-NLS-1$
			return tail.setDevice(device).makeRelative().makeUNC(isUNC());
		if (this.isRoot() && ((flags & IS_FOR_WINDOWS) == 0) == tail.isValidSegment(":")) //$NON-NLS-1$
			return tail.setDevice(device).makeAbsolute().makeUNC(isUNC());

		//concatenate the two segment arrays
		int myLen = segments.length;
		int tailLen = tail.segmentCount();
		String[] newSegments = new String[myLen + tailLen];
		System.arraycopy(segments, 0, newSegments, 0, myLen);
		for (int i = 0; i < tailLen; i++) {
			newSegments[myLen + i] = tail.segment(i);
		}
		//use my leading separators and the tail's trailing separator
		Path result = new Path(device, newSegments, (flags & (HAS_LEADING | IS_UNC | IS_FOR_WINDOWS)) | (tail.hasTrailingSeparator() ? HAS_TRAILING : 0));
		String tailFirstSegment = newSegments[myLen];
		if (tailFirstSegment.equals("..") || tailFirstSegment.equals(".")) { //$NON-NLS-1$ //$NON-NLS-2$
			result.canonicalize();
		}
		return result;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#append(java.lang.String)
	 */
	@Override
	public IPath append(String tail) {
		//optimize addition of a single segment
		if (tail.indexOf(SEPARATOR) == -1 && tail.indexOf('\\') == -1 && tail.indexOf(DEVICE_SEPARATOR) == -1) { //$NON-NLS-1$
			int tailLength = tail.length();
			if (tailLength < 3) {
				//some special cases
				if (tailLength == 0 || ".".equals(tail)) { //$NON-NLS-1$
					return this;
				}
				if ("..".equals(tail)) //$NON-NLS-1$
					return removeLastSegments(1);
			}
			//just add the segment
			int myLen = segments.length;
			String[] newSegments = new String[myLen + 1];
			System.arraycopy(segments, 0, newSegments, 0, myLen);
			newSegments[myLen] = tail;
			return new Path(device, newSegments, flags & ~HAS_TRAILING);
		}
		//go with easy implementation
		return append(new Path(tail, (flags & IS_FOR_WINDOWS) != 0));
	}

	/**
	 * Destructively converts this path to its canonical form.
	 * <p>
	 * In its canonical form, a path does not have any
	 * "." segments, and parent references ("..") are collapsed
	 * where possible.
	 * </p>
	 * @return true if the path was modified, and false otherwise.
	 */
	private boolean canonicalize() {
		//look for segments that need canonicalizing
		for (int i = 0, max = segments.length; i < max; i++) {
			String segment = segments[i];
			if (segment.charAt(0) == '.' && (segment.equals("..") || segment.equals("."))) { //$NON-NLS-1$ //$NON-NLS-2$
				//path needs to be canonicalized
				collapseParentReferences();
				//paths of length 0 have no trailing separator
				if (segments.length == 0)
					flags &= (HAS_LEADING | IS_UNC);
				//recompute hash because canonicalize affects hash
				flags = (flags & ALL_FLAGS) | (computeHashCode() << 4);
				return true;
			}
		}
		return false;
	}

	/* (Intentionally not included in javadoc)
	 * Clones this object.
	 */
	@Override
	public Object clone() {
		try {
			return super.clone();
		} catch (CloneNotSupportedException e) {
			return null;
		}
	}

	/**
	 * Destructively removes all occurrences of ".." segments from this path.
	 */
	private void collapseParentReferences() {
		int segmentCount = segments.length;
		String[] stack = new String[segmentCount];
		int stackPointer = 0;
		for (int i = 0; i < segmentCount; i++) {
			String segment = segments[i];
			if (segment.equals("..")) { //$NON-NLS-1$
				if (stackPointer == 0) {
					// if the stack is empty we are going out of our scope 
					// so we need to accumulate segments.  But only if the original
					// path is relative.  If it is absolute then we can't go any higher than
					// root so simply toss the .. references.
					if (!isAbsolute())
						stack[stackPointer++] = segment; //stack push
				} else {
					// if the top is '..' then we are accumulating segments so don't pop
					if ("..".equals(stack[stackPointer - 1])) //$NON-NLS-1$
						stack[stackPointer++] = ".."; //$NON-NLS-1$
					else
						stackPointer--;
					//stack pop
				}
				//collapse current references
			} else if (!segment.equals(".") || segmentCount == 1) //$NON-NLS-1$
				stack[stackPointer++] = segment; //stack push
		}
		//if the number of segments hasn't changed, then no modification needed
		if (stackPointer == segmentCount)
			return;
		//build the new segment array backwards by popping the stack
		String[] newSegments = new String[stackPointer];
		System.arraycopy(stack, 0, newSegments, 0, stackPointer);
		this.segments = newSegments;
	}

	/**
	 * Removes duplicate slashes from the given path, with the exception
	 * of leading double slash which represents a UNC path.
	 */
	private String collapseSlashes(String path) {
		int length = path.length();
		// if the path is only 0, 1 or 2 chars long then it could not possibly have illegal
		// duplicate slashes.
		if (length < 3)
			return path;
		// check for an occurrence of // in the path.  Start at index 1 to ensure we skip leading UNC //
		// If there are no // then there is nothing to collapse so just return.
		if (path.indexOf("//", 1) == -1) //$NON-NLS-1$
			return path;
		// We found an occurrence of // in the path so do the slow collapse.
		char[] result = new char[path.length()];
		int count = 0;
		boolean hasPrevious = false;
		char[] characters = path.toCharArray();
		for (int index = 0; index < characters.length; index++) {
			char c = characters[index];
			if (c == SEPARATOR) {
				if (hasPrevious) {
					// skip double slashes, except for beginning of UNC.
					// note that a UNC path can't have a device.
					if (device == null && index == 1) {
						result[count] = c;
						count++;
					}
				} else {
					hasPrevious = true;
					result[count] = c;
					count++;
				}
			} else {
				hasPrevious = false;
				result[count] = c;
				count++;
			}
		}
		return new String(result, 0, count);
	}

	/* (Intentionally not included in javadoc)
	 * Computes the hash code for this object.
	 */
	private int computeHashCode() {
		int hash = device == null ? 17 : device.hashCode();
		int segmentCount = segments.length;
		for (int i = 0; i < segmentCount; i++) {
			//this function tends to given a fairly even distribution
			hash = hash * 37 + segments[i].hashCode();
		}
		return hash;
	}

	/* (Intentionally not included in javadoc)
	 * Returns the size of the string that will be created by toString or toOSString.
	 */
	private int computeLength() {
		int length = 0;
		if (device != null)
			length += device.length();
		if ((flags & HAS_LEADING) != 0)
			length++;
		if ((flags & IS_UNC) != 0)
			length++;
		//add the segment lengths
		int max = segments.length;
		if (max > 0) {
			for (int i = 0; i < max; i++) {
				length += segments[i].length();
			}
			//add the separator lengths
			length += max - 1;
		}
		if ((flags & HAS_TRAILING) != 0)
			length++;
		return length;
	}

	/* (Intentionally not included in javadoc)
	 * Returns the number of segments in the given path
	 */
	private int computeSegmentCount(String path) {
		int len = path.length();
		if (len == 0 || (len == 1 && path.charAt(0) == SEPARATOR)) {
			return 0;
		}
		int count = 1;
		int prev = -1;
		int i;
		while ((i = path.indexOf(SEPARATOR, prev + 1)) != -1) {
			if (i != prev + 1 && i != len) {
				++count;
			}
			prev = i;
		}
		if (path.charAt(len - 1) == SEPARATOR) {
			--count;
		}
		return count;
	}

	/**
	 * Computes the segment array for the given canonicalized path.
	 */
	private String[] computeSegments(String path) {
		// performance sensitive --- avoid creating garbage
		int segmentCount = computeSegmentCount(path);
		if (segmentCount == 0)
			return NO_SEGMENTS;
		String[] newSegments = new String[segmentCount];
		int len = path.length();
		// check for initial slash
		int firstPosition = (path.charAt(0) == SEPARATOR) ? 1 : 0;
		// check for UNC
		if (firstPosition == 1 && len > 1 && (path.charAt(1) == SEPARATOR))
			firstPosition = 2;
		int lastPosition = (path.charAt(len - 1) != SEPARATOR) ? len - 1 : len - 2;
		// for non-empty paths, the number of segments is 
		// the number of slashes plus 1, ignoring any leading
		// and trailing slashes
		int next = firstPosition;
		for (int i = 0; i < segmentCount; i++) {
			int start = next;
			int end = path.indexOf(SEPARATOR, next);
			if (end == -1) {
				newSegments[i] = path.substring(start, lastPosition + 1);
			} else {
				newSegments[i] = path.substring(start, end);
			}
			next = end + 1;
		}
		return newSegments;
	}

	/**
	 * Returns the platform-neutral encoding of the given segment onto
	 * the given string buffer. This escapes literal colon characters with double colons.
	 */
	private void encodeSegment(String string, StringBuffer buf) {
		int len = string.length();
		for (int i = 0; i < len; i++) {
			char c = string.charAt(i);
			buf.append(c);
			if (c == DEVICE_SEPARATOR)
				buf.append(DEVICE_SEPARATOR);
		}
	}

	/* (Intentionally not included in javadoc)
	 * Compares objects for equality.
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (!(obj instanceof Path))
			return false;
		Path target = (Path) obj;
		//check leading separators and hash code
		if ((flags & HASH_MASK) != (target.flags & HASH_MASK))
			return false;
		String[] targetSegments = target.segments;
		int i = segments.length;
		//check segment count
		if (i != targetSegments.length)
			return false;
		//check segments in reverse order - later segments more likely to differ
		while (--i >= 0)
			if (!segments[i].equals(targetSegments[i]))
				return false;
		//check device last (least likely to differ)
		return device == target.device || (device != null && device.equals(target.device));
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#getDevice
	 */
	@Override
	public String getDevice() {
		return device;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#getFileExtension
	 */
	@Override
	public String getFileExtension() {
		if (hasTrailingSeparator()) {
			return null;
		}
		String lastSegment = lastSegment();
		if (lastSegment == null) {
			return null;
		}
		int index = lastSegment.lastIndexOf('.');
		if (index == -1) {
			return null;
		}
		return lastSegment.substring(index + 1);
	}

	/* (Intentionally not included in javadoc)
	 * Computes the hash code for this object.
	 */
	@Override
	public int hashCode() {
		return flags & HASH_MASK;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#hasTrailingSeparator2
	 */
	@Override
	public boolean hasTrailingSeparator() {
		return (flags & HAS_TRAILING) != 0;
	}

	/*
	 * Initialize the current path with the given string.
	 */
	private IPath initialize(String deviceString, String path, boolean forWindows) {
		Assert.isNotNull(path);
		this.device = deviceString;

		path = collapseSlashes(path);
		int len = path.length();

		//compute the flags bitmap
		if (len < 2) {
			if (len == 1 && path.charAt(0) == SEPARATOR) {
				this.flags = HAS_LEADING;
			} else {
				this.flags = 0;
			}
		} else {
			boolean hasLeading = path.charAt(0) == SEPARATOR;
			boolean isUNC = hasLeading && path.charAt(1) == SEPARATOR;
			//UNC path of length two has no trailing separator
			boolean hasTrailing = !(isUNC && len == 2) && path.charAt(len - 1) == SEPARATOR;
			flags = hasLeading ? HAS_LEADING : 0;
			if (isUNC)
				flags |= IS_UNC;
			if (hasTrailing)
				flags |= HAS_TRAILING;
		}
		if (forWindows) {
			flags |= IS_FOR_WINDOWS;
		}
		//compute segments and ensure canonical form
		segments = computeSegments(path);
		if (!canonicalize()) {
			//compute hash now because canonicalize didn't need to do it
			flags = (flags & ALL_FLAGS) | (computeHashCode() << 4);
		}
		return this;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#isAbsolute
	 */
	@Override
	public boolean isAbsolute() {
		//it's absolute if it has a leading separator
		return (flags & HAS_LEADING) != 0;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#isEmpty
	 */
	@Override
	public boolean isEmpty() {
		//true if no segments and no leading prefix
		return segments.length == 0 && ((flags & ALL_SEPARATORS) != HAS_LEADING);
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#isPrefixOf
	 */
	@Override
	public boolean isPrefixOf(IPath anotherPath) {
		if (device == null) {
			if (anotherPath.getDevice() != null) {
				return false;
			}
		} else {
			if (!device.equalsIgnoreCase(anotherPath.getDevice())) {
				return false;
			}
		}
		if (isEmpty() || (isRoot() && anotherPath.isAbsolute())) {
			return true;
		}
		int len = segments.length;
		if (len > anotherPath.segmentCount()) {
			return false;
		}
		for (int i = 0; i < len; i++) {
			if (!segments[i].equals(anotherPath.segment(i)))
				return false;
		}
		return true;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#isRoot
	 */
	@Override
	public boolean isRoot() {
		//must have no segments, a leading separator, and not be a UNC path.
		return this == ROOT || (segments.length == 0 && ((flags & ALL_SEPARATORS) == HAS_LEADING));
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#isUNC
	 */
	@Override
	public boolean isUNC() {
		if (device != null)
			return false;
		return (flags & IS_UNC) != 0;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#isValidPath(String)
	 */
	@Override
	public boolean isValidPath(String path) {
		return isValidPath(path, (flags & IS_FOR_WINDOWS) != 0);
	}

	/**
	 * Returns whether the given string is syntactically correct as a path on a
	 * POSIX file system. The path is correct if each of the segments in its
	 * canonicalized form is valid.
	 *
	 * @param path the path to check
	 * @return <code>true</code> if the given string is a valid path,
	 *    and <code>false</code> otherwise
	 * @see #isValidPosixSegment(String)
	 * @since 3.7
	 */
	public static boolean isValidPosixPath(String path) {
		return isValidPath(path, false);
	}

	/**
	 * Returns whether the given string is syntactically correct as a path on
	 * the Windows file system. The device id is the prefix up to and including
	 * the device separator (':'); the path proper is everything to the right of
	 * it, or the entire string if there is no device separator. The device id
	 * is not checked for validity; the path proper is correct if each of the
	 * segments in its canonicalized form is valid.
	 *
	 * @param path the path to check
	 * @return <code>true</code> if the given string is a valid path,
	 *    and <code>false</code> otherwise
	 * @see #isValidWindowsSegment(String)
	 * @since 3.7
	 */
	public static boolean isValidWindowsPath(String path) {
		return isValidPath(path, true);
	}

	/**
	 * Returns whether the given string is syntactically correct as a path on
	 * the specified file system. The device id is the prefix up to and
	 * including the device separator for the specified file system; the path
	 * proper is everything to the right of it, or the entire string if there is
	 * no device separator. When the specified platform is a file system with no
	 * meaningful device separator, the entire string is treated as the path
	 * proper. The device id is not checked for validity; the path proper is
	 * correct if each of the segments in its canonicalized form is valid.
	 *
	 * @param path the path to check
	 * @param forWindows true if the path is for the Windows file system
	 * @return <code>true</code> if the given string is a valid path,
	 *    and <code>false</code> otherwise
	 * @see #isValidSegment(String, boolean)
	 * @since 3.7
	 */
	private static boolean isValidPath(String path, boolean forWindows) {
		Path test = new Path(path, forWindows);
		for (int i = 0, max = test.segmentCount(); i < max; i++)
			if (!Path.isValidSegment(test.segment(i), forWindows))
				return false;
		return true;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#isValidSegment(String)
	 */
	@Override
	public boolean isValidSegment(String segment) {
		return isValidSegment(segment, (flags & IS_FOR_WINDOWS) != 0);
	}

	/**
	 * Returns whether the given string is valid as a segment in a path on a
	 * POSIX file system. The rules for valid segments are as follows:
	 * <ul>
	 * <li>the empty string is not valid
	 * <li>any string containing the slash character ('/') is not valid
	 * </ul>
	 *
	 * @param segment the path segment to check
	 * @return <code>true</code> if the given path segment is valid,
	 *    and <code>false</code> otherwise
	 * @since 3.7
	 */
	public static boolean isValidPosixSegment(String segment) {
		return isValidSegment(segment, false);
	}

	/**
	 * Returns whether the given string is valid as a segment in a path on the
	 * Windows file system. The rules for valid segments are as follows:
	 * <ul>
	 * <li>the empty string is not valid
	 * <li>any string containing the slash character ('/') is not valid
	 * <li>any string containing segment ('\') or device (':') separator
	 * characters is not valid
	 * </ul>
	 *
	 * @param segment the path segment to check
	 * @return <code>true</code> if the given path segment is valid,
	 *    and <code>false</code> otherwise
	 * @since 3.7
	 */
	public static boolean isValidWindowsSegment(String segment) {
		return isValidSegment(segment, true);
	}

	/**
	 * Returns whether the given string is valid as a segment in a path on the
	 * specified file system. The rules for valid segments are as follows:
	 * <ul>
	 * <li>the empty string is not valid
	 * <li>any string containing the slash character ('/') is not valid
	 * <li>any string containing segment or device separator characters on the
	 * specified file system, such as the backslash ('\') and colon (':') on
	 * Windows, is not valid
	 * </ul>
	 *
	 * @param segment the path segment to check
	 * @param forWindows true if the path is for the Windows file system
	 * @return <code>true</code> if the given path segment is valid,
	 *    and <code>false</code> otherwise
	 * @since 3.7
	 */
	private static boolean isValidSegment(String segment, boolean forWindows) {
		int size = segment.length();
		if (size == 0)
			return false;
		for (int i = 0; i < size; i++) {
			char c = segment.charAt(i);
			if (c == '/')
				return false;
			if (forWindows && (c == '\\' || c == ':'))
				return false;
		}
		return true;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#lastSegment()
	 */
	@Override
	public String lastSegment() {
		int len = segments.length;
		return len == 0 ? null : segments[len - 1];
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#makeAbsolute()
	 */
	@Override
	public IPath makeAbsolute() {
		if (isAbsolute()) {
			return this;
		}
		Path result = new Path(device, segments, flags | HAS_LEADING);
		//may need canonicalizing if it has leading ".." or "." segments
		if (result.segmentCount() > 0) {
			String first = result.segment(0);
			if (first.equals("..") || first.equals(".")) { //$NON-NLS-1$ //$NON-NLS-2$
				result.canonicalize();
			}
		}
		return result;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#makeRelative()
	 */
	@Override
	public IPath makeRelative() {
		if (!isAbsolute()) {
			return this;
		}
		return new Path(device, segments, flags & (HAS_TRAILING | IS_FOR_WINDOWS));
	}

	/**
	 * {@inheritDoc}
	 * @since org.eclipse.equinox.common 3.5
	 */
	@Override
	public IPath makeRelativeTo(IPath base) {
		//can't make relative if devices are not equal
		if (device != base.getDevice() && (device == null || !device.equalsIgnoreCase(base.getDevice())))
			return this;
		int commonLength = matchingFirstSegments(base);
		final int differenceLength = base.segmentCount() - commonLength;
		final int newSegmentLength = differenceLength + segmentCount() - commonLength;
		if (newSegmentLength == 0)
			return Path.EMPTY;
		String[] newSegments = new String[newSegmentLength];
		//add parent references for each segment different from the base
		Arrays.fill(newSegments, 0, differenceLength, ".."); //$NON-NLS-1$
		//append the segments of this path not in common with the base
		System.arraycopy(segments, commonLength, newSegments, differenceLength, newSegmentLength - differenceLength);
		return new Path(null, newSegments, flags & (HAS_TRAILING | IS_FOR_WINDOWS));
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#makeUNC(boolean)
	 */
	@Override
	public IPath makeUNC(boolean toUNC) {
		// if we are already in the right form then just return
		if (!(toUNC ^ isUNC()))
			return this;

		int newSeparators = this.flags;
		if (toUNC) {
			newSeparators |= HAS_LEADING | IS_UNC;
		} else {
			//mask out the UNC bit
			newSeparators &= HAS_LEADING | HAS_TRAILING | IS_FOR_WINDOWS;
		}
		return new Path(toUNC ? null : device, segments, newSeparators);
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#matchingFirstSegments(IPath)
	 */
	@Override
	public int matchingFirstSegments(IPath anotherPath) {
		Assert.isNotNull(anotherPath);
		int anotherPathLen = anotherPath.segmentCount();
		int max = Math.min(segments.length, anotherPathLen);
		int count = 0;
		for (int i = 0; i < max; i++) {
			if (!segments[i].equals(anotherPath.segment(i))) {
				return count;
			}
			count++;
		}
		return count;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#removeFileExtension()
	 */
	@Override
	public IPath removeFileExtension() {
		String extension = getFileExtension();
		if (extension == null || extension.equals("")) { //$NON-NLS-1$
			return this;
		}
		String lastSegment = lastSegment();
		int index = lastSegment.lastIndexOf(extension) - 1;
		return removeLastSegments(1).append(lastSegment.substring(0, index));
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#removeFirstSegments(int)
	 */
	@Override
	public IPath removeFirstSegments(int count) {
		if (count == 0)
			return this;
		if (count >= segments.length) {
			return new Path(device, NO_SEGMENTS, flags & IS_FOR_WINDOWS);
		}
		Assert.isLegal(count > 0);
		int newSize = segments.length - count;
		String[] newSegments = new String[newSize];
		System.arraycopy(this.segments, count, newSegments, 0, newSize);

		//result is always a relative path
		return new Path(device, newSegments, flags & (HAS_TRAILING | IS_FOR_WINDOWS));
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#removeLastSegments(int)
	 */
	@Override
	public IPath removeLastSegments(int count) {
		if (count == 0)
			return this;
		if (count >= segments.length) {
			//result will have no trailing separator
			return new Path(device, NO_SEGMENTS, flags & (HAS_LEADING | IS_UNC | IS_FOR_WINDOWS));
		}
		Assert.isLegal(count > 0);
		int newSize = segments.length - count;
		String[] newSegments = new String[newSize];
		System.arraycopy(this.segments, 0, newSegments, 0, newSize);
		return new Path(device, newSegments, flags);
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#removeTrailingSeparator()
	 */
	@Override
	public IPath removeTrailingSeparator() {
		if (!hasTrailingSeparator()) {
			return this;
		}
		return new Path(device, segments, flags & (HAS_LEADING | IS_UNC | IS_FOR_WINDOWS));
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#segment(int)
	 */
	@Override
	public String segment(int index) {
		if (index >= segments.length)
			return null;
		return segments[index];
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#segmentCount()
	 */
	@Override
	public int segmentCount() {
		return segments.length;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#segments()
	 */
	@Override
	public String[] segments() {
		String[] segmentCopy = new String[segments.length];
		System.arraycopy(segments, 0, segmentCopy, 0, segments.length);
		return segmentCopy;
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#setDevice(String)
	 */
	@Override
	public IPath setDevice(String value) {
		if (value != null) {
			Assert.isTrue(value.indexOf(IPath.DEVICE_SEPARATOR) == (value.length() - 1), "Last character should be the device separator"); //$NON-NLS-1$
		}
		//return the receiver if the device is the same
		if (value == device || (value != null && value.equals(device)))
			return this;

		return new Path(value, segments, flags);
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#toFile()
	 */
	@Override
	public File toFile() {
		return new File(toOSString());
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#toOSString()
	 */
	@Override
	public String toOSString() {
		//Note that this method is identical to toString except
		//it uses the OS file separator instead of the path separator
		int resultSize = computeLength();
		if (resultSize <= 0)
			return EMPTY_STRING;
		char FILE_SEPARATOR = File.separatorChar;
		char[] result = new char[resultSize];
		int offset = 0;
		if (device != null) {
			int size = device.length();
			device.getChars(0, size, result, offset);
			offset += size;
		}
		if ((flags & HAS_LEADING) != 0)
			result[offset++] = FILE_SEPARATOR;
		if ((flags & IS_UNC) != 0)
			result[offset++] = FILE_SEPARATOR;
		int len = segments.length - 1;
		if (len >= 0) {
			//append all but the last segment, with file separators
			for (int i = 0; i < len; i++) {
				int size = segments[i].length();
				segments[i].getChars(0, size, result, offset);
				offset += size;
				result[offset++] = FILE_SEPARATOR;
			}
			//append the last segment
			int size = segments[len].length();
			segments[len].getChars(0, size, result, offset);
			offset += size;
		}
		if ((flags & HAS_TRAILING) != 0)
			result[offset++] = FILE_SEPARATOR;
		return new String(result);
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#toPortableString()
	 */
	@Override
	public String toPortableString() {
		int resultSize = computeLength();
		if (resultSize <= 0)
			return EMPTY_STRING;
		StringBuffer result = new StringBuffer(resultSize);
		if (device != null)
			result.append(device);
		if ((flags & HAS_LEADING) != 0)
			result.append(SEPARATOR);
		if ((flags & IS_UNC) != 0)
			result.append(SEPARATOR);
		int len = segments.length;
		//append all segments with separators
		for (int i = 0; i < len; i++) {
			if (segments[i].indexOf(DEVICE_SEPARATOR) >= 0)
				encodeSegment(segments[i], result);
			else
				result.append(segments[i]);
			if (i < len - 1 || (flags & HAS_TRAILING) != 0)
				result.append(SEPARATOR);
		}
		return result.toString();
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#toString()
	 */
	@Override
	public String toString() {
		int resultSize = computeLength();
		if (resultSize <= 0)
			return EMPTY_STRING;
		char[] result = new char[resultSize];
		int offset = 0;
		if (device != null) {
			int size = device.length();
			device.getChars(0, size, result, offset);
			offset += size;
		}
		if ((flags & HAS_LEADING) != 0)
			result[offset++] = SEPARATOR;
		if ((flags & IS_UNC) != 0)
			result[offset++] = SEPARATOR;
		int len = segments.length - 1;
		if (len >= 0) {
			//append all but the last segment, with separators
			for (int i = 0; i < len; i++) {
				int size = segments[i].length();
				segments[i].getChars(0, size, result, offset);
				offset += size;
				result[offset++] = SEPARATOR;
			}
			//append the last segment
			int size = segments[len].length();
			segments[len].getChars(0, size, result, offset);
			offset += size;
		}
		if ((flags & HAS_TRAILING) != 0)
			result[offset++] = SEPARATOR;
		return new String(result);
	}

	/* (Intentionally not included in javadoc)
	 * @see IPath#uptoSegment(int)
	 */
	@Override
	public IPath uptoSegment(int count) {
		if (count == 0)
			return new Path(device, NO_SEGMENTS, flags & (HAS_LEADING | IS_UNC | IS_FOR_WINDOWS));
		if (count >= segments.length)
			return this;
		Assert.isTrue(count > 0, "Invalid parameter to Path.uptoSegment"); //$NON-NLS-1$
		String[] newSegments = new String[count];
		System.arraycopy(segments, 0, newSegments, 0, count);
		return new Path(device, newSegments, flags);
	}
}
