comparison org.eclipse.equinox.common/src/org/eclipse/core/runtime/Path.d @ 105:bbe49769ec18

...
author Frank Benoit <benoit@tionex.de>
date Sun, 08 Nov 2009 12:42:30 +0100
parents dccb717aa902
children
comparison
equal deleted inserted replaced
104:88652073d1c2 105:bbe49769ec18
2 * Copyright (c) 2000, 2008 IBM Corporation and others. 2 * Copyright (c) 2000, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials 3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0 4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at 5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html 6 * http://www.eclipse.org/legal/epl-v10.html
7 * 7 *
8 * Contributors: 8 * Contributors:
9 * IBM Corporation - initial API and implementation 9 * IBM Corporation - initial API and implementation
10 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/ 10 *******************************************************************************/
13 module org.eclipse.core.runtime.Path; 11 // Port to the D programming language:
14 12 // Frank Benoit <benoit@tionex.de>
15 import tango.io.FilePath; 13 module org.eclipse.core.runtimePath;
16 static import tango.io.Path;
17 import org.eclipse.core.runtime.IPath;
18 import org.eclipse.core.runtime.Assert;
19 14
20 import java.lang.all; 15 import java.lang.all;
21 16
22 import tango.io.model.IFile; 17 import org.eclipse.core.runtimeIPath; // packageimport
23 18 import org.eclipse.core.runtimeAssert; // packageimport
24 /** 19
20 import java.io.File;
21
22 /**
25 * The standard implementation of the <code>IPath</code> interface. 23 * The standard implementation of the <code>IPath</code> interface.
26 * Paths are always maintained in canonicalized form. That is, parent 24 * Paths are always maintained in canonicalized form. That is, parent
27 * references (i.e., <code>../../</code>) and duplicate separators are 25 * references (i.e., <code>../../</code>) and duplicate separators are
28 * resolved. For example, 26 * resolved. For example,
29 * <pre> new Path("/a/b").append("../foo/bar")</pre> 27 * <pre> (new Path("/a/b")).append("../foo/bar")</pre>
30 * will yield the path 28 * will yield the path
31 * <pre> /a/foo/bar</pre> 29 * <pre> /a/foo/bar</pre>
32 * <p> 30 * <p>
33 * This class can be used without OSGi running. 31 * This class can be used without OSGi running.
34 * </p><p> 32 * </p><p>
38 * @see IPath 36 * @see IPath
39 * @noextend This class is not intended to be subclassed by clients. 37 * @noextend This class is not intended to be subclassed by clients.
40 */ 38 */
41 public class Path : IPath, Cloneable { 39 public class Path : IPath, Cloneable {
42 /** masks for separator values */ 40 /** masks for separator values */
43 private static const int HAS_LEADING = 1; 41 private static final int HAS_LEADING = 1;
44 private static const int IS_UNC = 2; 42 private static final int IS_UNC = 2;
45 private static const int HAS_TRAILING = 4; 43 private static final int HAS_TRAILING = 4;
46 44
47 private static const int ALL_SEPARATORS = HAS_LEADING | IS_UNC | HAS_TRAILING; 45 private static final int ALL_SEPARATORS = HAS_LEADING | IS_UNC | HAS_TRAILING;
48 46
49 /** Constant empty string value. */ 47 /** Constant empty string value. */
50 private static const String EMPTY_STRING = ""; //$NON-NLS-1$ 48 private static final String EMPTY_STRING = ""; //$NON-NLS-1$
51 49
52 /** Constant value indicating no segments */ 50 /** Constant value indicating no segments */
53 private static const String[] NO_SEGMENTS = null; 51 private static final String[] NO_SEGMENTS = new String[0];
54 52
55 /** Constant value containing the empty path with no device. */ 53 /** Constant value containing the empty path with no device. */
56 public static const Path EMPTY; 54 public static final Path EMPTY = new Pathcast(EMPTY_STRING);
57 55
58 /** Mask for all bits that are involved in the hash code */ 56 /** Mask for all bits that are involved in the hash code */
59 private static const int HASH_MASK = ~HAS_TRAILING; 57 private static final int HASH_MASK = ~HAS_TRAILING;
60 58
61 /** Constant root path string (<code>"/"</code>). */ 59 /** Constant root path string (<code>"/"</code>). */
62 private static const String ROOT_STRING = "/"; //$NON-NLS-1$ 60 private static final String ROOT_STRING = "/"; //$NON-NLS-1$
63 61
64 /** Constant value containing the root path with no device. */ 62 /** Constant value containing the root path with no device. */
65 public static const Path ROOT; 63 public static final Path ROOT = new Pathcast(ROOT_STRING);
66 64
67 /** Constant value indicating if the current platform is Windows */ 65 /** Constant value indicating if the current platform is Windows */
68 version(Windows){ 66 private static final bool WINDOWS = java.io.File.separatorChar is '\\';
69 private static const bool WINDOWS = true;
70 }
71 else {
72 private static const bool WINDOWS = false;
73 }
74
75 static this(){
76 EMPTY = new Path(EMPTY_STRING);
77 ROOT = new Path(ROOT_STRING);
78 }
79 67
80 /** The device id string. May be null if there is no device. */ 68 /** The device id string. May be null if there is no device. */
81 private String device = null; 69 private String device = null;
82 70
83 //Private implementation note: the segments and separators 71 //Private implementation note: the segments and separators
84 //arrays are never modified, so that they can be shared between 72 //arrays are never modified, so that they can be shared between
85 //path instances 73 //path instances
86 74
87 /** The path segments */ 75 /** The path segments */
88 private String[] segments_; 76 private String[] segments;
89 77
90 /** flags indicating separators (has leading, is UNC, has trailing) */ 78 /** flags indicating separators (has leading, is UNC, has trailing) */
91 private int separators; 79 private int separators;
92 80
93 /** 81 /**
94 * Constructs a new path from the given string path. 82 * Constructs a new path from the given string path.
95 * The string path must represent a valid file system path 83 * The string path must represent a valid file system path
96 * on the local file system. 84 * on the local file system.
97 * The path is canonicalized and double slashes are removed 85 * The path is canonicalized and double slashes are removed
98 * except at the beginning. (to handle UNC paths). All forward 86 * except at the beginning. (to handle UNC paths). All forward
99 * slashes ('/') are treated as segment delimiters, and any 87 * slashes ('/') are treated as segment delimiters, and any
100 * segment and device delimiters for the local file system are 88 * segment and device delimiters for the local file system are
101 * also respected. 89 * also respected.
106 */ 94 */
107 public static IPath fromOSString(String pathString) { 95 public static IPath fromOSString(String pathString) {
108 return new Path(pathString); 96 return new Path(pathString);
109 } 97 }
110 98
111 /** 99 /**
112 * Constructs a new path from the given path string. 100 * Constructs a new path from the given path string.
113 * The path string must have been produced by a previous 101 * The path string must have been produced by a previous
114 * call to <code>IPath.toPortableString</code>. 102 * call to <code>IPath.toPortableString</code>.
115 * 103 *
116 * @param pathString the portable path string 104 * @param pathString the portable path string
117 * @see IPath#toPortableString() 105 * @see IPath#toPortableString()
118 * @since 3.1 106 * @since 3.1
119 */ 107 */
120 public static IPath fromPortableString(String pathString) { 108 public static IPath fromPortableString(String pathString) {
121 int firstMatch = pathString.indexOf(DEVICE_SEPARATOR) + 1; 109 int firstMatch = pathString.indexOfcast(DEVICE_SEPARATOR) + 1;
122 //no extra work required if no device characters 110 //no extra work required if no device characters
123 if (firstMatch <= 0) 111 if (firstMatch <= 0)
124 return (new Path()).initialize(null, pathString); 112 return (new Path()).initialize(null, pathString);
125 //if we find a single colon, then the path has a device 113 //if we find a single colon, then the path has a device
126 String devicePart = null; 114 String devicePart = null;
127 int pathLength = pathString.length; 115 int pathLength = pathString.length();
128 if (firstMatch is pathLength || pathString.charAt(firstMatch) !is DEVICE_SEPARATOR) { 116 if (firstMatch is pathLength || pathString.charAt(firstMatch) !is DEVICE_SEPARATOR) {
129 devicePart = pathString.substring(0, firstMatch); 117 devicePart = pathString.substring(0, firstMatch);
130 pathString = pathString.substring(firstMatch, pathLength); 118 pathString = pathString.substring(firstMatch, pathLength);
131 } 119 }
132 //optimize for no colon literals 120 //optimize for no colon literals
133 if (pathString.indexOf(DEVICE_SEPARATOR) is -1) 121 if (pathString.indexOfcast(DEVICE_SEPARATOR) is -1)
134 return (new Path()).initialize(devicePart, pathString); 122 return (new Path()).initialize(devicePart, pathString);
135 //contract colon literals 123 //contract colon literals
136 char[] chars = pathString/+.toCharArray()+/; 124 char[] chars = pathString.toCharArray();
137 int readOffset = 0, writeOffset = 0, length = chars.length; 125 int readOffset = 0, writeOffset = 0, length = chars.length;
138 while (readOffset < length) { 126 while (readOffset < length) {
139 if (chars[readOffset] is DEVICE_SEPARATOR) 127 if (chars[readOffset] is DEVICE_SEPARATOR)
140 if (++readOffset >= length) 128 if (++readOffset >= length)
141 break; 129 break;
142 chars[writeOffset++] = chars[readOffset++]; 130 chars[writeOffset++] = chars[readOffset++];
143 } 131 }
144 return (new Path()).initialize(devicePart, chars[ 0 .. writeOffset] ); 132 return (new Path()).initialize(devicePart, new String(chars, 0, writeOffset));
145 } 133 }
146 134
147 /* (Intentionally not included in javadoc) 135 /* (Intentionally not included in javadoc)
148 * Private constructor. 136 * Private constructor.
149 */ 137 */
150 private this() { 138 private this() {
151 // not allowed 139 // not allowed
152 } 140 }
153 141
154 /** 142 /**
155 * Constructs a new path from the given string path. 143 * Constructs a new path from the given string path.
156 * The string path must represent a valid file system path 144 * The string path must represent a valid file system path
157 * on the local file system. 145 * on the local file system.
158 * The path is canonicalized and double slashes are removed 146 * The path is canonicalized and double slashes are removed
159 * except at the beginning. (to handle UNC paths). All forward 147 * except at the beginning. (to handle UNC paths). All forward
160 * slashes ('/') are treated as segment delimiters, and any 148 * slashes ('/') are treated as segment delimiters, and any
161 * segment and device delimiters for the local file system are 149 * segment and device delimiters for the local file system are
162 * also respected (such as colon (':') and backslash ('\') on some file systems). 150 * also respected (such as colon (':') and backslash ('\') on some file systems).
168 String devicePart = null; 156 String devicePart = null;
169 if (WINDOWS) { 157 if (WINDOWS) {
170 //convert backslash to forward slash 158 //convert backslash to forward slash
171 fullPath = fullPath.indexOf('\\') is -1 ? fullPath : fullPath.replace('\\', SEPARATOR); 159 fullPath = fullPath.indexOf('\\') is -1 ? fullPath : fullPath.replace('\\', SEPARATOR);
172 //extract device 160 //extract device
173 int i = fullPath.indexOf(DEVICE_SEPARATOR); 161 int i = fullPath.indexOfcast(DEVICE_SEPARATOR);
174 if (i !is -1) { 162 if (i !is -1) {
175 //remove leading slash from device part to handle output of URL.getFile() 163 //remove leading slash from device part to handle output of URL.getFile()
176 int start = fullPath.charAt(0) is SEPARATOR ? 1 : 0; 164 int start = fullPath.charAt(0) is SEPARATOR ? 1 : 0;
177 devicePart = fullPath.substring(start, i + 1); 165 devicePart = fullPath.substring(start, i + 1);
178 fullPath = fullPath.substring(i + 1, fullPath.length); 166 fullPath = fullPath.substring(i + 1, fullPath.length());
179 } 167 }
180 } 168 }
181 initialize(devicePart, fullPath); 169 initialize(devicePart, fullPath);
182 } 170 }
183 171
184 /** 172 /**
185 * Constructs a new path from the given device id and string path. 173 * Constructs a new path from the given device id and string path.
186 * The given string path must be valid. 174 * The given string path must be valid.
187 * The path is canonicalized and double slashes are removed except 175 * The path is canonicalized and double slashes are removed except
188 * at the beginning (to handle UNC paths). All forward 176 * at the beginning (to handle UNC paths). All forward
189 * slashes ('/') are treated as segment delimiters, and any 177 * slashes ('/') are treated as segment delimiters, and any
204 } 192 }
205 193
206 /* (Intentionally not included in javadoc) 194 /* (Intentionally not included in javadoc)
207 * Private constructor. 195 * Private constructor.
208 */ 196 */
209 private this(String device, String[] segments_, int _separators) { 197 private this(String device, String[] segments, int _separators) {
210 // no segment validations are done for performance reasons 198 // no segment validations are done for performance reasons
211 this.segments_ = segments_; 199 this.segments = segments;
212 this.device = device; 200 this.device = device;
213 //hash code is cached in all but the bottom three bits of the separators field 201 //hash code is cached in all but the bottom three bits of the separators field
214 this.separators = (computeHashCode() << 3) | (_separators & ALL_SEPARATORS); 202 this.separators = (computeHashCode() << 3) | (_separators & ALL_SEPARATORS);
215 } 203 }
216 204
218 * @see IPath#addFileExtension 206 * @see IPath#addFileExtension
219 */ 207 */
220 public IPath addFileExtension(String extension) { 208 public IPath addFileExtension(String extension) {
221 if (isRoot() || isEmpty() || hasTrailingSeparator()) 209 if (isRoot() || isEmpty() || hasTrailingSeparator())
222 return this; 210 return this;
223 int len = segments_.length; 211 int len = segments.length;
224 String[] newSegments = new String[len]; 212 String[] newSegments = new String[len];
225 System.arraycopy(segments_, 0, newSegments, 0, len - 1); 213 System.arraycopy(segments, 0, newSegments, 0, len - 1);
226 newSegments[len - 1] = segments_[len - 1] ~ '.' ~ extension; 214 newSegments[len - 1] = segments[len - 1] + '.' + extension;
227 return new Path(device, newSegments, separators); 215 return new Path(device, newSegments, separators);
228 } 216 }
229 217
230 /* (Intentionally not included in javadoc) 218 /* (Intentionally not included in javadoc)
231 * @see IPath#addTrailingSeparator 219 * @see IPath#addTrailingSeparator
234 if (hasTrailingSeparator() || isRoot()) { 222 if (hasTrailingSeparator() || isRoot()) {
235 return this; 223 return this;
236 } 224 }
237 //XXX workaround, see 1GIGQ9V 225 //XXX workaround, see 1GIGQ9V
238 if (isEmpty()) { 226 if (isEmpty()) {
239 return new Path(device, segments_, HAS_LEADING); 227 return new Path(device, segments, HAS_LEADING);
240 } 228 }
241 return new Path(device, segments_, separators | HAS_TRAILING); 229 return new Path(device, segments, separators | HAS_TRAILING);
242 } 230 }
243 231
244 /* (Intentionally not included in javadoc) 232 /* (Intentionally not included in javadoc)
245 * @see IPath#append(IPath) 233 * @see IPath#append(IPath)
246 */ 234 */
253 return tail.setDevice(device).makeRelative().makeUNC(isUNC()); 241 return tail.setDevice(device).makeRelative().makeUNC(isUNC());
254 if (this.isRoot()) 242 if (this.isRoot())
255 return tail.setDevice(device).makeAbsolute().makeUNC(isUNC()); 243 return tail.setDevice(device).makeAbsolute().makeUNC(isUNC());
256 244
257 //concatenate the two segment arrays 245 //concatenate the two segment arrays
258 int myLen = segments_.length; 246 int myLen = segments.length;
259 int tailLen = tail.segmentCount(); 247 int tailLen = tail.segmentCount();
260 String[] newSegments = new String[myLen + tailLen]; 248 String[] newSegments = new String[myLen + tailLen];
261 System.arraycopy(segments_, 0, newSegments, 0, myLen); 249 System.arraycopy(segments, 0, newSegments, 0, myLen);
262 for (int i = 0; i < tailLen; i++) { 250 for (int i = 0; i < tailLen; i++) {
263 newSegments[myLen + i] = tail.segment(i); 251 newSegments[myLen + i] = tail.segment(i);
264 } 252 }
265 //use my leading separators and the tail's trailing separator 253 //use my leading separators and the tail's trailing separator
266 Path result = new Path(device, newSegments, (separators & (HAS_LEADING | IS_UNC)) | (tail.hasTrailingSeparator() ? HAS_TRAILING : 0)); 254 Path result = new Path(device, newSegments, (separators & (HAS_LEADING | IS_UNC)) | (tail.hasTrailingSeparator() ? HAS_TRAILING : 0));
267 String tailFirstSegment = newSegments[myLen]; 255 String tailFirstSegment = newSegments[myLen];
268 if (tailFirstSegment.equals("..") || tailFirstSegment.equals(".")) { //$NON-NLS-1$ //$NON-NLS-2$ 256 if (tailFirstSegment.opEquals("..") || tailFirstSegment.opEquals(".")) { //$NON-NLS-1$ //$NON-NLS-2$
269 result.canonicalize(); 257 result.canonicalize();
270 } 258 }
271 return result; 259 return result;
272 } 260 }
273 261
274 /* (Intentionally not included in javadoc) 262 /* (Intentionally not included in javadoc)
275 * @see IPath#append(java.lang.String) 263 * @see IPath#append(java.lang.String)
276 */ 264 */
277 public IPath append(String tail) { 265 public IPath append(String tail) {
278 //optimize addition of a single segment 266 //optimize addition of a single segment
279 if (tail.indexOf(SEPARATOR) is -1 && tail.indexOf("\\") is -1 && tail.indexOf(DEVICE_SEPARATOR) is -1) { //$NON-NLS-1$ 267 if (tail.indexOfcast(SEPARATOR) is -1 && tail.indexOf("\\") is -1 && tail.indexOfcast(DEVICE_SEPARATOR) is -1) { //$NON-NLS-1$
280 int tailLength = tail.length; 268 int tailLength = tail.length();
281 if (tailLength < 3) { 269 if (tailLength < 3) {
282 //some special cases 270 //some special cases
283 if (tailLength is 0 || ".".equals(tail)) { //$NON-NLS-1$ 271 if (tailLength is 0 || ".".opEquals(tail)) { //$NON-NLS-1$
284 return this; 272 return this;
285 } 273 }
286 if ("..".equals(tail)) //$NON-NLS-1$ 274 if ("..".opEquals(tail)) //$NON-NLS-1$
287 return removeLastSegments(1); 275 return removeLastSegments(1);
288 } 276 }
289 //just add the segment 277 //just add the segment
290 int myLen = segments_.length; 278 int myLen = segments.length;
291 String[] newSegments = new String[myLen + 1]; 279 String[] newSegments = new String[myLen + 1];
292 System.arraycopy(segments_, 0, newSegments, 0, myLen); 280 System.arraycopy(segments, 0, newSegments, 0, myLen);
293 newSegments[myLen] = tail; 281 newSegments[myLen] = tail;
294 return new Path(device, newSegments, separators & ~HAS_TRAILING); 282 return new Path(device, newSegments, separators & ~HAS_TRAILING);
295 } 283 }
296 //go with easy implementation 284 //go with easy implementation
297 return append(new Path(tail)); 285 return append(new Path(tail));
306 * </p> 294 * </p>
307 * @return true if the path was modified, and false otherwise. 295 * @return true if the path was modified, and false otherwise.
308 */ 296 */
309 private bool canonicalize() { 297 private bool canonicalize() {
310 //look for segments that need canonicalizing 298 //look for segments that need canonicalizing
311 for (int i = 0, max = segments_.length; i < max; i++) { 299 for (int i = 0, max = segments.length; i < max; i++) {
312 String segment = segments_[i]; 300 String segment = segments[i];
313 if (segment.charAt(0) is '.' && (segment.equals("..") || segment.equals("."))) { //$NON-NLS-1$ //$NON-NLS-2$ 301 if (segment.charAt(0) is '.' && (segment.opEquals("..") || segment.opEquals("."))) { //$NON-NLS-1$ //$NON-NLS-2$
314 //path needs to be canonicalized 302 //path needs to be canonicalized
315 collapseParentReferences(); 303 collapseParentReferences();
316 //paths of length 0 have no trailing separator 304 //paths of length 0 have no trailing separator
317 if (segments_.length is 0) 305 if (segments.length is 0)
318 separators &= (HAS_LEADING | IS_UNC); 306 separators &= (HAS_LEADING | IS_UNC);
319 //recompute hash because canonicalize affects hash 307 //recompute hash because canonicalize affects hash
320 separators = (separators & ALL_SEPARATORS) | (computeHashCode() << 3); 308 separators = (separators & ALL_SEPARATORS) | (computeHashCode() << 3);
321 return true; 309 return true;
322 } 310 }
325 } 313 }
326 314
327 /* (Intentionally not included in javadoc) 315 /* (Intentionally not included in javadoc)
328 * Clones this object. 316 * Clones this object.
329 */ 317 */
330 public Path clone() { 318 public Object clone() {
331 return new Path(device, segments_, separators); 319 try {
320 return super.clone();
321 } catch (CloneNotSupportedException e) {
322 return null;
323 }
332 } 324 }
333 325
334 /** 326 /**
335 * Destructively removes all occurrences of ".." segments from this path. 327 * Destructively removes all occurrences of ".." segments from this path.
336 */ 328 */
337 private void collapseParentReferences() { 329 private void collapseParentReferences() {
338 int segmentCount = segments_.length; 330 int segmentCount = segments.length;
339 String[] stack = new String[segmentCount]; 331 String[] stack = new String[segmentCount];
340 int stackPointer = 0; 332 int stackPointer = 0;
341 for (int i = 0; i < segmentCount; i++) { 333 for (int i = 0; i < segmentCount; i++) {
342 String segment = segments_[i]; 334 String segment = segments[i];
343 if (segment.equals("..")) { //$NON-NLS-1$ 335 if (segment.opEquals("..")) { //$NON-NLS-1$
344 if (stackPointer is 0) { 336 if (stackPointer is 0) {
345 // if the stack is empty we are going out of our scope 337 // if the stack is empty we are going out of our scope
346 // so we need to accumulate segments. But only if the original 338 // so we need to accumulate segments. But only if the original
347 // path is relative. If it is absolute then we can't go any higher than 339 // path is relative. If it is absolute then we can't go any higher than
348 // root so simply toss the .. references. 340 // root so simply toss the .. references.
349 if (!isAbsolute()) 341 if (!isAbsolute())
350 stack[stackPointer++] = segment; //stack push 342 stack[stackPointer++] = segment; //stack push
351 } else { 343 } else {
352 // if the top is '..' then we are accumulating segments so don't pop 344 // if the top is '..' then we are accumulating segments so don't pop
353 if ("..".equals(stack[stackPointer - 1])) //$NON-NLS-1$ 345 if ("..".opEquals(stack[stackPointer - 1])) //$NON-NLS-1$
354 stack[stackPointer++] = ".."; //$NON-NLS-1$ 346 stack[stackPointer++] = ".."; //$NON-NLS-1$
355 else 347 else
356 stackPointer--; 348 stackPointer--;
357 //stack pop 349 //stack pop
358 } 350 }
359 //collapse current references 351 //collapse current references
360 } else if (!segment.equals(".") || segmentCount is 1) //$NON-NLS-1$ 352 } else if (!segment.opEquals(".") || segmentCount is 1) //$NON-NLS-1$
361 stack[stackPointer++] = segment; //stack push 353 stack[stackPointer++] = segment; //stack push
362 } 354 }
363 //if the number of segments hasn't changed, then no modification needed 355 //if the number of segments hasn't changed, then no modification needed
364 if (stackPointer is segmentCount) 356 if (stackPointer is segmentCount)
365 return; 357 return;
366 //build the new segment array backwards by popping the stack 358 //build the new segment array backwards by popping the stack
367 String[] newSegments = new String[stackPointer]; 359 String[] newSegments = new String[stackPointer];
368 System.arraycopy(stack, 0, newSegments, 0, stackPointer); 360 System.arraycopy(stack, 0, newSegments, 0, stackPointer);
369 this.segments_ = newSegments; 361 this.segments = newSegments;
370 } 362 }
371 363
372 /** 364 /**
373 * Removes duplicate slashes from the given path, with the exception 365 * Removes duplicate slashes from the given path, with the exception
374 * of leading double slash which represents a UNC path. 366 * of leading double slash which represents a UNC path.
375 */ 367 */
376 private String collapseSlashes(String path) { 368 private String collapseSlashes(String path) {
377 int length = path.length; 369 int length = path.length();
378 // if the path is only 0, 1 or 2 chars long then it could not possibly have illegal 370 // if the path is only 0, 1 or 2 chars long then it could not possibly have illegal
379 // duplicate slashes. 371 // duplicate slashes.
380 if (length < 3) 372 if (length < 3)
381 return path; 373 return path;
382 // check for an occurrence of // in the path. Start at index 1 to ensure we skip leading UNC // 374 // check for an occurrence of // in the path. Start at index 1 to ensure we skip leading UNC //
383 // If there are no // then there is nothing to collapse so just return. 375 // If there are no // then there is nothing to collapse so just return.
384 if (path.indexOf("//", 1) is -1) //$NON-NLS-1$ 376 if (path.indexOf("//", 1) is -1) //$NON-NLS-1$
385 return path; 377 return path;
386 // We found an occurrence of // in the path so do the slow collapse. 378 // We found an occurrence of // in the path so do the slow collapse.
387 char[] result = new char[path.length]; 379 char[] result = new char[path.length()];
388 int count = 0; 380 int count = 0;
389 bool hasPrevious = false; 381 bool hasPrevious = false;
390 char[] characters = path/+.toCharArray()+/; 382 char[] characters = path.toCharArray();
391 for (int index = 0; index < characters.length; index++) { 383 for (int index = 0; index < characters.length; index++) {
392 char c = characters[index]; 384 char c = characters[index];
393 if (c is SEPARATOR) { 385 if (c is SEPARATOR) {
394 if (hasPrevious) { 386 if (hasPrevious) {
395 // skip double slashes, except for beginning of UNC. 387 // skip double slashes, except for beginning of UNC.
407 hasPrevious = false; 399 hasPrevious = false;
408 result[count] = c; 400 result[count] = c;
409 count++; 401 count++;
410 } 402 }
411 } 403 }
412 return result[ 0 .. count]; 404 return new String(result, 0, count);
413 } 405 }
414 406
415 /* (Intentionally not included in javadoc) 407 /* (Intentionally not included in javadoc)
416 * Computes the hash code for this object. 408 * Computes the hash code for this object.
417 */ 409 */
418 private int computeHashCode() { 410 private int computeHashCode() {
419 int hash = device.length is 0 ? 17 : java.lang.all.toHash(device); 411 int hash = device is null ? 17 : device.toHash();
420 int segmentCount = segments_.length; 412 int segmentCount = segments.length;
421 for (int i = 0; i < segmentCount; i++) { 413 for (int i = 0; i < segmentCount; i++) {
422 //this function tends to given a fairly even distribution 414 //this function tends to given a fairly even distribution
423 hash = hash * 37 + java.lang.all.toHash(segments_[i]); 415 hash = hash * 37 + segments[i].toHash();
424 } 416 }
425 return hash; 417 return hash;
426 } 418 }
427 419
428 /* (Intentionally not included in javadoc) 420 /* (Intentionally not included in javadoc)
429 * Returns the size of the string that will be created by toString or toOSString. 421 * Returns the size of the string that will be created by toString or toOSString.
430 */ 422 */
431 private int computeLength() { 423 private int computeLength() {
432 int length = 0; 424 int length = 0;
433 if (device !is null) 425 if (device !is null)
434 length += device.length; 426 length += device.length();
435 if ((separators & HAS_LEADING) !is 0) 427 if ((separators & HAS_LEADING) !is 0)
436 length++; 428 length++;
437 if ((separators & IS_UNC) !is 0) 429 if ((separators & IS_UNC) !is 0)
438 length++; 430 length++;
439 //add the segment lengths 431 //add the segment lengths
440 int max = segments_.length; 432 int max = segments.length;
441 if (max > 0) { 433 if (max > 0) {
442 for (int i = 0; i < max; i++) { 434 for (int i = 0; i < max; i++) {
443 length += segments_[i].length; 435 length += segments[i].length();
444 } 436 }
445 //add the separator lengths 437 //add the separator lengths
446 length += max - 1; 438 length += max - 1;
447 } 439 }
448 if ((separators & HAS_TRAILING) !is 0) 440 if ((separators & HAS_TRAILING) !is 0)
452 444
453 /* (Intentionally not included in javadoc) 445 /* (Intentionally not included in javadoc)
454 * Returns the number of segments in the given path 446 * Returns the number of segments in the given path
455 */ 447 */
456 private int computeSegmentCount(String path) { 448 private int computeSegmentCount(String path) {
457 int len = path.length; 449 int len = path.length();
458 if (len is 0 || (len is 1 && path.charAt(0) is SEPARATOR)) { 450 if (len is 0 || (len is 1 && path.charAt(0) is SEPARATOR)) {
459 return 0; 451 return 0;
460 } 452 }
461 int count = 1; 453 int count = 1;
462 int prev = -1; 454 int prev = -1;
480 // performance sensitive --- avoid creating garbage 472 // performance sensitive --- avoid creating garbage
481 int segmentCount = computeSegmentCount(path); 473 int segmentCount = computeSegmentCount(path);
482 if (segmentCount is 0) 474 if (segmentCount is 0)
483 return NO_SEGMENTS; 475 return NO_SEGMENTS;
484 String[] newSegments = new String[segmentCount]; 476 String[] newSegments = new String[segmentCount];
485 int len = path.length; 477 int len = path.length();
486 // check for initial slash 478 // check for initial slash
487 int firstPosition = (path.charAt(0) is SEPARATOR) ? 1 : 0; 479 int firstPosition = (path.charAt(0) is SEPARATOR) ? 1 : 0;
488 // check for UNC 480 // check for UNC
489 if (firstPosition is 1 && len > 1 && (path.charAt(1) is SEPARATOR)) 481 if (firstPosition is 1 && len > 1 && (path.charAt(1) is SEPARATOR))
490 firstPosition = 2; 482 firstPosition = 2;
491 int lastPosition = (path.charAt(len - 1) !is SEPARATOR) ? len - 1 : len - 2; 483 int lastPosition = (path.charAt(len - 1) !is SEPARATOR) ? len - 1 : len - 2;
492 // for non-empty paths, the number of segments is 484 // for non-empty paths, the number of segments is
493 // the number of slashes plus 1, ignoring any leading 485 // the number of slashes plus 1, ignoring any leading
494 // and trailing slashes 486 // and trailing slashes
495 int next = firstPosition; 487 int next = firstPosition;
496 for (int i = 0; i < segmentCount; i++) { 488 for (int i = 0; i < segmentCount; i++) {
497 int start = next; 489 int start = next;
509 /** 501 /**
510 * Returns the platform-neutral encoding of the given segment onto 502 * Returns the platform-neutral encoding of the given segment onto
511 * the given string buffer. This escapes literal colon characters with double colons. 503 * the given string buffer. This escapes literal colon characters with double colons.
512 */ 504 */
513 private void encodeSegment(String string, StringBuffer buf) { 505 private void encodeSegment(String string, StringBuffer buf) {
514 int len = string.length; 506 int len = string.length();
515 for (int i = 0; i < len; i++) { 507 for (int i = 0; i < len; i++) {
516 char c = string.charAt(i); 508 char c = string.charAt(i);
517 buf.append(c); 509 buf.append(c);
518 if (c is DEVICE_SEPARATOR) 510 if (c is DEVICE_SEPARATOR)
519 buf.append(DEVICE_SEPARATOR); 511 buf.appendcast(DEVICE_SEPARATOR);
520 } 512 }
521 } 513 }
522 514
523 /* (Intentionally not included in javadoc) 515 /* (Intentionally not included in javadoc)
524 * Compares objects for equality. 516 * Compares objects for equality.
525 */ 517 */
526 public override int opEquals(Object obj) { 518 public override equals_t opEquals(Object obj) {
527 if (this is obj) 519 if (this is obj)
528 return true; 520 return true;
529 if (!(cast(Path)obj)) 521 if (!( null !is cast(Path)obj ))
530 return false; 522 return false;
531 Path target = cast(Path) obj; 523 Path target = cast(Path) obj;
532 //check leading separators and hash code 524 //check leading separators and hash code
533 if ((separators & HASH_MASK) !is (target.separators & HASH_MASK)) 525 if ((separators & HASH_MASK) !is (target.separators & HASH_MASK))
534 return false; 526 return false;
535 String[] targetSegments = target.segments_; 527 String[] targetSegments = target.segments;
536 int i = segments_.length; 528 int i = segments.length;
537 //check segment count 529 //check segment count
538 if (i !is targetSegments.length) 530 if (i !is targetSegments.length)
539 return false; 531 return false;
540 //check segments in reverse order - later segments more likely to differ 532 //check segments in reverse order - later segments more likely to differ
541 while (--i >= 0) 533 while (--i >= 0)
542 if (!segments_[i].equals(targetSegments[i])) 534 if (!segments[i].opEquals(targetSegments[i]))
543 return false; 535 return false;
544 //check device last (least likely to differ) 536 //check device last (least likely to differ)
545 return device is target.device || (device !is null && device.equals(target.device)); 537 return device is target.device || (device !is null && device.opEquals(target.device));
546 } 538 }
547 539
548 /* (Intentionally not included in javadoc) 540 /* (Intentionally not included in javadoc)
549 * @see IPath#getDevice 541 * @see IPath#getDevice
550 */ 542 */
586 578
587 /* 579 /*
588 * Initialize the current path with the given string. 580 * Initialize the current path with the given string.
589 */ 581 */
590 private IPath initialize(String deviceString, String path) { 582 private IPath initialize(String deviceString, String path) {
591 //Assert.isNotNull(path); // allow for SWT 583 Assert.isNotNull(path);
592 this.device = deviceString; 584 this.device = deviceString;
593 585
594 path = collapseSlashes(path); 586 path = collapseSlashes(path);
595 int len = path.length; 587 int len = path.length();
596 588
597 //compute the separators array 589 //compute the separators array
598 if (len < 2) { 590 if (len < 2) {
599 if (len is 1 && path.charAt(0) is SEPARATOR) { 591 if (len is 1 && path.charAt(0) is SEPARATOR) {
600 this.separators = HAS_LEADING; 592 this.separators = HAS_LEADING;
611 separators |= IS_UNC; 603 separators |= IS_UNC;
612 if (hasTrailing) 604 if (hasTrailing)
613 separators |= HAS_TRAILING; 605 separators |= HAS_TRAILING;
614 } 606 }
615 //compute segments and ensure canonical form 607 //compute segments and ensure canonical form
616 segments_ = computeSegments(path); 608 segments = computeSegments(path);
617 if (!canonicalize()) { 609 if (!canonicalize()) {
618 //compute hash now because canonicalize didn't need to do it 610 //compute hash now because canonicalize didn't need to do it
619 separators = (separators & ALL_SEPARATORS) | (computeHashCode() << 3); 611 separators = (separators & ALL_SEPARATORS) | (computeHashCode() << 3);
620 } 612 }
621 return this; 613 return this;
632 /* (Intentionally not included in javadoc) 624 /* (Intentionally not included in javadoc)
633 * @see IPath#isEmpty 625 * @see IPath#isEmpty
634 */ 626 */
635 public bool isEmpty() { 627 public bool isEmpty() {
636 //true if no segments and no leading prefix 628 //true if no segments and no leading prefix
637 return segments_.length is 0 && ((separators & ALL_SEPARATORS) !is HAS_LEADING); 629 return segments.length is 0 && ((separators & ALL_SEPARATORS) !is HAS_LEADING);
638 630
639 } 631 }
640 632
641 /* (Intentionally not included in javadoc) 633 /* (Intentionally not included in javadoc)
642 * @see IPath#isPrefixOf 634 * @see IPath#isPrefixOf
652 } 644 }
653 } 645 }
654 if (isEmpty() || (isRoot() && anotherPath.isAbsolute())) { 646 if (isEmpty() || (isRoot() && anotherPath.isAbsolute())) {
655 return true; 647 return true;
656 } 648 }
657 int len = segments_.length; 649 int len = segments.length;
658 if (len > anotherPath.segmentCount()) { 650 if (len > anotherPath.segmentCount()) {
659 return false; 651 return false;
660 } 652 }
661 for (int i = 0; i < len; i++) { 653 for (int i = 0; i < len; i++) {
662 if (!segments_[i].equals(anotherPath.segment(i))) 654 if (!segments[i].opEquals(anotherPath.segment(i)))
663 return false; 655 return false;
664 } 656 }
665 return true; 657 return true;
666 } 658 }
667 659
668 /* (Intentionally not included in javadoc) 660 /* (Intentionally not included in javadoc)
669 * @see IPath#isRoot 661 * @see IPath#isRoot
670 */ 662 */
671 public bool isRoot() { 663 public bool isRoot() {
672 //must have no segments, a leading separator, and not be a UNC path. 664 //must have no segments, a leading separator, and not be a UNC path.
673 return this is ROOT || (segments_.length is 0 && ((separators & ALL_SEPARATORS) is HAS_LEADING)); 665 return this is ROOT || (segments.length is 0 && ((separators & ALL_SEPARATORS) is HAS_LEADING));
674 } 666 }
675 667
676 /* (Intentionally not included in javadoc) 668 /* (Intentionally not included in javadoc)
677 * @see IPath#isUNC 669 * @see IPath#isUNC
678 */ 670 */
695 687
696 /* (Intentionally not included in javadoc) 688 /* (Intentionally not included in javadoc)
697 * @see IPath#isValidSegment(String) 689 * @see IPath#isValidSegment(String)
698 */ 690 */
699 public bool isValidSegment(String segment) { 691 public bool isValidSegment(String segment) {
700 int size = segment.length; 692 int size = segment.length();
701 if (size is 0) 693 if (size is 0)
702 return false; 694 return false;
703 for (int i = 0; i < size; i++) { 695 for (int i = 0; i < size; i++) {
704 char c = segment.charAt(i); 696 char c = segment.charAt(i);
705 if (c is '/') 697 if (c is '/')
712 704
713 /* (Intentionally not included in javadoc) 705 /* (Intentionally not included in javadoc)
714 * @see IPath#lastSegment() 706 * @see IPath#lastSegment()
715 */ 707 */
716 public String lastSegment() { 708 public String lastSegment() {
717 int len = segments_.length; 709 int len = segments.length;
718 return len is 0 ? null : segments_[len - 1]; 710 return len is 0 ? null : segments[len - 1];
719 } 711 }
720 712
721 /* (Intentionally not included in javadoc) 713 /* (Intentionally not included in javadoc)
722 * @see IPath#makeAbsolute() 714 * @see IPath#makeAbsolute()
723 */ 715 */
724 public IPath makeAbsolute() { 716 public IPath makeAbsolute() {
725 if (isAbsolute()) { 717 if (isAbsolute()) {
726 return this; 718 return this;
727 } 719 }
728 Path result = new Path(device, segments_, separators | HAS_LEADING); 720 Path result = new Path(device, segments, separators | HAS_LEADING);
729 //may need canonicalizing if it has leading ".." or "." segments 721 //may need canonicalizing if it has leading ".." or "." segments
730 if (result.segmentCount() > 0) { 722 if (result.segmentCount() > 0) {
731 String first = result.segment(0); 723 String first = result.segment(0);
732 if (first.equals("..") || first.equals(".")) { //$NON-NLS-1$ //$NON-NLS-2$ 724 if (first.opEquals("..") || first.opEquals(".")) { //$NON-NLS-1$ //$NON-NLS-2$
733 result.canonicalize(); 725 result.canonicalize();
734 } 726 }
735 } 727 }
736 return result; 728 return result;
737 } 729 }
741 */ 733 */
742 public IPath makeRelative() { 734 public IPath makeRelative() {
743 if (!isAbsolute()) { 735 if (!isAbsolute()) {
744 return this; 736 return this;
745 } 737 }
746 return new Path(device, segments_, separators & HAS_TRAILING); 738 return new Path(device, segments, separators & HAS_TRAILING);
747 } 739 }
748 740
749 /* (Intentionally not included in javadoc) 741 /* (Intentionally not included in javadoc)
750 * @see IPath#makeUNC(bool) 742 * @see IPath#makeUNC(boolean)
751 */ 743 */
752 public IPath makeUNC(bool toUNC) { 744 public IPath makeUNC(bool toUNC) {
753 // if we are already in the right form then just return 745 // if we are already in the right form then just return
754 if (!(toUNC ^ isUNC())) 746 if (!(toUNC ^ isUNC()))
755 return this; 747 return this;
759 newSeparators |= HAS_LEADING | IS_UNC; 751 newSeparators |= HAS_LEADING | IS_UNC;
760 } else { 752 } else {
761 //mask out the UNC bit 753 //mask out the UNC bit
762 newSeparators &= HAS_LEADING | HAS_TRAILING; 754 newSeparators &= HAS_LEADING | HAS_TRAILING;
763 } 755 }
764 return new Path(toUNC ? null : device, segments_, newSeparators); 756 return new Path(toUNC ? null : device, segments, newSeparators);
765 } 757 }
766 758
767 /* (Intentionally not included in javadoc) 759 /* (Intentionally not included in javadoc)
768 * @see IPath#matchingFirstSegments(IPath) 760 * @see IPath#matchingFirstSegments(IPath)
769 */ 761 */
770 public int matchingFirstSegments(IPath anotherPath) { 762 public int matchingFirstSegments(IPath anotherPath) {
771 Assert.isNotNull( cast(Object) anotherPath); 763 Assert.isNotNull(anotherPath);
772 int anotherPathLen = anotherPath.segmentCount(); 764 int anotherPathLen = anotherPath.segmentCount();
773 int max = Math.min(segments_.length, anotherPathLen); 765 int max = Math.min(segments.length, anotherPathLen);
774 int count = 0; 766 int count = 0;
775 for (int i = 0; i < max; i++) { 767 for (int i = 0; i < max; i++) {
776 if (!segments_[i].equals(anotherPath.segment(i))) { 768 if (!segments[i].opEquals(anotherPath.segment(i))) {
777 return count; 769 return count;
778 } 770 }
779 count++; 771 count++;
780 } 772 }
781 return count; 773 return count;
784 /* (Intentionally not included in javadoc) 776 /* (Intentionally not included in javadoc)
785 * @see IPath#removeFileExtension() 777 * @see IPath#removeFileExtension()
786 */ 778 */
787 public IPath removeFileExtension() { 779 public IPath removeFileExtension() {
788 String extension = getFileExtension(); 780 String extension = getFileExtension();
789 if (extension is null || extension.equals("")) { //$NON-NLS-1$ 781 if (extension is null || extension.opEquals("")) { //$NON-NLS-1$
790 return this; 782 return this;
791 } 783 }
792 String lastSegment = lastSegment(); 784 String lastSegment = lastSegment();
793 int index = lastSegment.lastIndexOf(extension) - 1; 785 int index = lastSegment.lastIndexOf(extension) - 1;
794 return removeLastSegments(1).append(lastSegment.substring(0, index)); 786 return removeLastSegments(1).append(lastSegment.substring(0, index));
798 * @see IPath#removeFirstSegments(int) 790 * @see IPath#removeFirstSegments(int)
799 */ 791 */
800 public IPath removeFirstSegments(int count) { 792 public IPath removeFirstSegments(int count) {
801 if (count is 0) 793 if (count is 0)
802 return this; 794 return this;
803 if (count >= segments_.length) { 795 if (count >= segments.length) {
804 return new Path(device, NO_SEGMENTS, 0); 796 return new Path(device, NO_SEGMENTS, 0);
805 } 797 }
806 Assert.isLegal(count > 0); 798 Assert.isLegal(count > 0);
807 int newSize = segments_.length - count; 799 int newSize = segments.length - count;
808 String[] newSegments = new String[newSize]; 800 String[] newSegments = new String[newSize];
809 System.arraycopy(this.segments_, count, newSegments, 0, newSize); 801 System.arraycopy(this.segments, count, newSegments, 0, newSize);
810 802
811 //result is always a relative path 803 //result is always a relative path
812 return new Path(device, newSegments, separators & HAS_TRAILING); 804 return new Path(device, newSegments, separators & HAS_TRAILING);
813 } 805 }
814 806
816 * @see IPath#removeLastSegments(int) 808 * @see IPath#removeLastSegments(int)
817 */ 809 */
818 public IPath removeLastSegments(int count) { 810 public IPath removeLastSegments(int count) {
819 if (count is 0) 811 if (count is 0)
820 return this; 812 return this;
821 if (count >= segments_.length) { 813 if (count >= segments.length) {
822 //result will have no trailing separator 814 //result will have no trailing separator
823 return new Path(device, NO_SEGMENTS, separators & (HAS_LEADING | IS_UNC)); 815 return new Path(device, NO_SEGMENTS, separators & (HAS_LEADING | IS_UNC));
824 } 816 }
825 Assert.isLegal(count > 0); 817 Assert.isLegal(count > 0);
826 int newSize = segments_.length - count; 818 int newSize = segments.length - count;
827 String[] newSegments = new String[newSize]; 819 String[] newSegments = new String[newSize];
828 System.arraycopy(this.segments_, 0, newSegments, 0, newSize); 820 System.arraycopy(this.segments, 0, newSegments, 0, newSize);
829 return new Path(device, newSegments, separators); 821 return new Path(device, newSegments, separators);
830 } 822 }
831 823
832 /* (Intentionally not included in javadoc) 824 /* (Intentionally not included in javadoc)
833 * @see IPath#removeTrailingSeparator() 825 * @see IPath#removeTrailingSeparator()
834 */ 826 */
835 public IPath removeTrailingSeparator() { 827 public IPath removeTrailingSeparator() {
836 if (!hasTrailingSeparator()) { 828 if (!hasTrailingSeparator()) {
837 return this; 829 return this;
838 } 830 }
839 return new Path(device, segments_, separators & (HAS_LEADING | IS_UNC)); 831 return new Path(device, segments, separators & (HAS_LEADING | IS_UNC));
840 } 832 }
841 833
842 /* (Intentionally not included in javadoc) 834 /* (Intentionally not included in javadoc)
843 * @see IPath#segment(int) 835 * @see IPath#segment(int)
844 */ 836 */
845 public String segment(int index) { 837 public String segment(int index) {
846 if (index >= segments_.length) 838 if (index >= segments.length)
847 return null; 839 return null;
848 return segments_[index]; 840 return segments[index];
849 } 841 }
850 842
851 /* (Intentionally not included in javadoc) 843 /* (Intentionally not included in javadoc)
852 * @see IPath#segmentCount() 844 * @see IPath#segmentCount()
853 */ 845 */
854 public int segmentCount() { 846 public int segmentCount() {
855 return segments_.length; 847 return segments.length;
856 } 848 }
857 849
858 /* (Intentionally not included in javadoc) 850 /* (Intentionally not included in javadoc)
859 * @see IPath#segments() 851 * @see IPath#segments()
860 */ 852 */
861 public String[] segments() { 853 public String[] segments() {
862 String[] segmentCopy = new String[](segments_.length); 854 String[] segmentCopy = new String[segments.length];
863 System.arraycopy(segments_, 0, segmentCopy, 0, segments_.length); 855 System.arraycopy(segments, 0, segmentCopy, 0, segments.length);
864 return segmentCopy; 856 return segmentCopy;
865 } 857 }
866 858
867 /* (Intentionally not included in javadoc) 859 /* (Intentionally not included in javadoc)
868 * @see IPath#setDevice(String) 860 * @see IPath#setDevice(String)
869 */ 861 */
870 public IPath setDevice(String value) { 862 public IPath setDevice(String value) {
871 if (value !is null) { 863 if (value !is null) {
872 Assert.isTrue(value.indexOf(IPath.DEVICE_SEPARATOR) is (value.length - 1), "Last character should be the device separator"); //$NON-NLS-1$ 864 Assert.isTrue(value.indexOfcast(IPath.DEVICE_SEPARATOR) is (value.length() - 1), "Last character should be the device separator"); //$NON-NLS-1$
873 } 865 }
874 //return the receiver if the device is the same 866 //return the receiver if the device is the same
875 if (value is device || (value !is null && value.equals(device))) 867 if (value is device || (value !is null && value.opEquals(device)))
876 return this; 868 return this;
877 869
878 return new Path(value, segments_, separators); 870 return new Path(value, segments, separators);
879 } 871 }
880 872
881 /* (Intentionally not included in javadoc) 873 /* (Intentionally not included in javadoc)
882 * @see IPath#toFile() 874 * @see IPath#toFile()
883 */ 875 */
884 public FilePath toFile() { 876 public File toFile() {
885 return new FilePath(tango.io.Path.standard(toOSString())); 877 return new File(toOSString());
886 } 878 }
887 879
888 /* (Intentionally not included in javadoc) 880 /* (Intentionally not included in javadoc)
889 * @see IPath#toOSString() 881 * @see IPath#toOSString()
890 */ 882 */
892 //Note that this method is identical to toString except 884 //Note that this method is identical to toString except
893 //it uses the OS file separator instead of the path separator 885 //it uses the OS file separator instead of the path separator
894 int resultSize = computeLength(); 886 int resultSize = computeLength();
895 if (resultSize <= 0) 887 if (resultSize <= 0)
896 return EMPTY_STRING; 888 return EMPTY_STRING;
897 char FILE_SEPARATOR = FileConst.PathSeparatorChar; 889 char FILE_SEPARATOR = File.separatorChar;
898 char[] result = new char[resultSize]; 890 char[] result = new char[resultSize];
899 int offset = 0; 891 int offset = 0;
900 if (device !is null) { 892 if (device !is null) {
901 int size = device.length; 893 int size = device.length();
902 device.getChars(0, size, result, offset); 894 device.getChars(0, size, result, offset);
903 offset += size; 895 offset += size;
904 } 896 }
905 if ((separators & HAS_LEADING) !is 0) 897 if ((separators & HAS_LEADING) !is 0)
906 result[offset++] = FILE_SEPARATOR; 898 result[offset++] = FILE_SEPARATOR;
907 if ((separators & IS_UNC) !is 0) 899 if ((separators & IS_UNC) !is 0)
908 result[offset++] = FILE_SEPARATOR; 900 result[offset++] = FILE_SEPARATOR;
909 int len = segments_.length - 1; 901 int len = segments.length - 1;
910 if (len >= 0) { 902 if (len >= 0) {
911 //append all but the last segment, with separators 903 //append all but the last segment, with separators
912 for (int i = 0; i < len; i++) { 904 for (int i = 0; i < len; i++) {
913 int size = segments_[i].length; 905 int size = segments[i].length();
914 segments_[i].getChars(0, size, result, offset); 906 segments[i].getChars(0, size, result, offset);
915 offset += size; 907 offset += size;
916 result[offset++] = FILE_SEPARATOR; 908 result[offset++] = FILE_SEPARATOR;
917 } 909 }
918 //append the last segment 910 //append the last segment
919 int size = segments_[len].length; 911 int size = segments[len].length();
920 segments_[len].getChars(0, size, result, offset); 912 segments[len].getChars(0, size, result, offset);
921 offset += size; 913 offset += size;
922 } 914 }
923 if ((separators & HAS_TRAILING) !is 0) 915 if ((separators & HAS_TRAILING) !is 0)
924 result[offset++] = FILE_SEPARATOR; 916 result[offset++] = FILE_SEPARATOR;
925 return result; 917 return new String(result);
926 } 918 }
927 919
928 /* (Intentionally not included in javadoc) 920 /* (Intentionally not included in javadoc)
929 * @see IPath#toPortableString() 921 * @see IPath#toPortableString()
930 */ 922 */
934 return EMPTY_STRING; 926 return EMPTY_STRING;
935 StringBuffer result = new StringBuffer(resultSize); 927 StringBuffer result = new StringBuffer(resultSize);
936 if (device !is null) 928 if (device !is null)
937 result.append(device); 929 result.append(device);
938 if ((separators & HAS_LEADING) !is 0) 930 if ((separators & HAS_LEADING) !is 0)
939 result.append(SEPARATOR); 931 result.appendcast(SEPARATOR);
940 if ((separators & IS_UNC) !is 0) 932 if ((separators & IS_UNC) !is 0)
941 result.append(SEPARATOR); 933 result.appendcast(SEPARATOR);
942 int len = segments_.length; 934 int len = segments.length;
943 //append all segments with separators 935 //append all segments with separators
944 for (int i = 0; i < len; i++) { 936 for (int i = 0; i < len; i++) {
945 if (segments_[i].indexOf(DEVICE_SEPARATOR) >= 0) 937 if (segments[i].indexOfcast(DEVICE_SEPARATOR) >= 0)
946 encodeSegment(segments_[i], result); 938 encodeSegment(segments[i], result);
947 else 939 else
948 result.append(segments_[i]); 940 result.append(segments[i]);
949 if (i < len - 1 || (separators & HAS_TRAILING) !is 0) 941 if (i < len - 1 || (separators & HAS_TRAILING) !is 0)
950 result.append(SEPARATOR); 942 result.appendcast(SEPARATOR);
951 } 943 }
952 return result.toString(); 944 return result.toString();
953 } 945 }
954 946
955 /* (Intentionally not included in javadoc) 947 /* (Intentionally not included in javadoc)
956 * @see IPath#toString() 948 * @see IPath#toString()
957 */ 949 */
958 public override String toString() { 950 public String toString() {
959 int resultSize = computeLength(); 951 int resultSize = computeLength();
960 if (resultSize <= 0) 952 if (resultSize <= 0)
961 return EMPTY_STRING; 953 return EMPTY_STRING;
962 char[] result = new char[resultSize]; 954 char[] result = new char[resultSize];
963 int offset = 0; 955 int offset = 0;
964 if (device !is null) { 956 if (device !is null) {
965 int size = device.length; 957 int size = device.length();
966 device.getChars(0, size, result, offset); 958 device.getChars(0, size, result, offset);
967 offset += size; 959 offset += size;
968 } 960 }
969 if ((separators & HAS_LEADING) !is 0) 961 if ((separators & HAS_LEADING) !is 0)
970 result[offset++] = SEPARATOR; 962 result[offset++] = SEPARATOR;
971 if ((separators & IS_UNC) !is 0) 963 if ((separators & IS_UNC) !is 0)
972 result[offset++] = SEPARATOR; 964 result[offset++] = SEPARATOR;
973 int len = segments_.length - 1; 965 int len = segments.length - 1;
974 if (len >= 0) { 966 if (len >= 0) {
975 //append all but the last segment, with separators 967 //append all but the last segment, with separators
976 for (int i = 0; i < len; i++) { 968 for (int i = 0; i < len; i++) {
977 int size = segments_[i].length; 969 int size = segments[i].length();
978 segments_[i].getChars(0, size, result, offset); 970 segments[i].getChars(0, size, result, offset);
979 offset += size; 971 offset += size;
980 result[offset++] = SEPARATOR; 972 result[offset++] = SEPARATOR;
981 } 973 }
982 //append the last segment 974 //append the last segment
983 int size = segments_[len].length; 975 int size = segments[len].length();
984 segments_[len].getChars(0, size, result, offset); 976 segments[len].getChars(0, size, result, offset);
985 offset += size; 977 offset += size;
986 } 978 }
987 if ((separators & HAS_TRAILING) !is 0) 979 if ((separators & HAS_TRAILING) !is 0)
988 result[offset++] = SEPARATOR; 980 result[offset++] = SEPARATOR;
989 return result; 981 return new String(result);
990 } 982 }
991 983
992 /* (Intentionally not included in javadoc) 984 /* (Intentionally not included in javadoc)
993 * @see IPath#uptoSegment(int) 985 * @see IPath#uptoSegment(int)
994 */ 986 */
995 public IPath uptoSegment(int count) { 987 public IPath uptoSegment(int count) {
996 if (count is 0) 988 if (count is 0)
997 return new Path(device, NO_SEGMENTS, separators & (HAS_LEADING | IS_UNC)); 989 return new Path(device, NO_SEGMENTS, separators & (HAS_LEADING | IS_UNC));
998 if (count >= segments_.length) 990 if (count >= segments.length)
999 return this; 991 return this;
1000 Assert.isTrue(count > 0, "Invalid parameter to Path.uptoSegment"); //$NON-NLS-1$ 992 Assert.isTrue(count > 0, "Invalid parameter to Path.uptoSegment"); //$NON-NLS-1$
1001 String[] newSegments = new String[count]; 993 String[] newSegments = new String[count];
1002 System.arraycopy(segments_, 0, newSegments, 0, count); 994 System.arraycopy(segments, 0, newSegments, 0, count);
1003 return new Path(device, newSegments, separators); 995 return new Path(device, newSegments, separators);
1004 } 996 }
1005 } 997 }