Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/hartmath/util/Misc.java


1   /*
2    * MiscUtilities.java - Various miscallaneous utility functions
3    * Copyright (C) 1999, 2000, 2001 Slava Pestov
4    * Portions copyright (C) 2000 Richard S. Hall
5    * Portions copyright (C) 2001 Dirk Moebius
6    *
7    * This program is free software; you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation; either version 2
10   * of the License, or any later version.
11   *
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, write to the Free Software
19   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20   */
21  
22  package com.hartmath.util;
23  
24  import javax.swing.JMenuItem;
25  import java.io.*;
26  import java.util.Vector;
27  import java.util.StringTokenizer;
28  import org.gjt.sp.util.Log;
29  
30  /**
31   * Class with several useful miscellaneous functions.<p>
32   *
33   * It provides methods for converting file names to class names, for
34   * constructing path names, and for various indentation calculations.
35   * A quicksort implementation is also available.
36   *
37   * @author Slava Pestov
38   * @version $Id: Misc.java,v 1.1 2001/10/06 13:30:21 khartlage Exp $
39   */
40  public class Misc
41  {
42          /**
43           * Converts a file name to a class name. All slash characters are
44           * replaced with periods and the trailing '.class' is removed.
45           * @param name The file name
46           */
47          public static String fileToClass(String name)
48          {
49                  char[] clsName = name.toCharArray();
50                  for(int i = clsName.length - 6; i >= 0; i--)
51                          if(clsName[i] == '/')
52                                  clsName[i] = '.';
53                  return new String(clsName,0,clsName.length - 6);
54          }
55  
56          /**
57           * Converts a class name to a file name. All periods are replaced
58           * with slashes and the '.class' extension is added.
59           * @param name The class name
60           */
61          public static String classToFile(String name)
62          {
63                  return name.replace('.','/').concat(".class");
64          }
65  
66          /**
67           * Constructs an absolute path name from a directory and another
68           * path name.
69           * @param parent The directory
70           * @param path The path name
71           */
72          public static String constructPath(String parent, String path)
73          {
74                  if(new File(path).isAbsolute())
75                          return canonPath(path);
76  
77                  if(parent == null)
78                          parent = System.getProperty("user.dir");
79  
80                  // have to handle these cases specially on windows.
81                  if(File.separatorChar == '\\')
82                  {
83                          if(path.length() == 2 && path.charAt(1) == ':')
84                                  return path;
85                          if(path.startsWith("/") || path.startsWith("\\"))
86                                  parent = parent.substring(0,2);
87                  }
88  
89                  if(parent.endsWith(File.separator) || path.endsWith("/"))
90                          return canonPath(parent + path);
91                  else
92                          return canonPath(parent + File.separator + path);
93          }
94  
95          /**
96           * Constructs an absolute path name from three path components.
97           * @param parent The parent directory
98           * @param path1 The first path
99           * @param path2 The second path
100          */
101         public static String constructPath(String parent,
102                 String path1, String path2)
103         {
104                 return constructPath(constructPath(parent,path1),path2);
105         }
106 
107         /**
108          * Like constructPath(), except <code>path</code> will be
109          * appended to <code>parent</code> even if it is absolute.
110          * @param path
111          * @param parent
112          */
113         public static String concatPath(String parent, String path)
114         {
115                 // Make all child paths relative.
116                 if (path.startsWith(File.separator))
117                         path = path.substring(1);
118                 else if ((path.length() >= 3) && (path.charAt(1) == ':'))
119                         path = path.replace(':', File.separatorChar);
120 
121                 if (parent == null)
122                         parent = System.getProperty("user.dir");
123 
124                 if (parent.endsWith(File.separator))
125                         return parent + path;
126                 else
127                         return parent + File.separator + path;
128         }
129 
130         /**
131          * Returns the extension of the specified filename, or an empty
132          * string if there is none.
133          * @param name The file name
134          */
135         public static String getFileExtension(String name)
136         {
137                 int index = name.indexOf('.');
138                 if(index == -1)
139                         return "";
140                 else
141                         return name.substring(index);
142         }
143 
144         /**
145          * For use with local files only - returns the last component
146          * of the specified path.
147          * @param path The path name
148          */
149         public static String getFileName(String path)
150         {
151                 int count = Math.max(0,path.length() - 2);
152                 int index1 = path.lastIndexOf(File.separatorChar,count);
153                 int index2 = path.lastIndexOf('/',count);
154 
155                 return path.substring(Math.max(index1,index2) + 1);
156         }
157 
158         /**
159          * @deprecated Call getParentOfPath() instead
160          */
161         public static String getFileParent(String path)
162         {
163                 return getParentOfPath(path);
164         }
165 
166         /**
167          * For use with local files only - returns the parent of the
168          * specified path.
169          * @param path The path name
170          * @since jEdit 2.6pre5
171          */
172         public static String getParentOfPath(String path)
173         {
174                 // ignore last character of path to properly handle
175                 // paths like /foo/bar/
176                 int count = Math.max(0,path.length() - 2);
177                 int index = path.lastIndexOf(File.separatorChar,count);
178                 if(index == -1)
179                         index = path.lastIndexOf('/',count);
180                 if(index == -1)
181                 {
182                         // this ensures that getFileParent("protocol:"), for
183                         // example, is "protocol:" and not "".
184                         index = path.lastIndexOf(':');
185                 }
186 
187                 return path.substring(0,index + 1);
188         }
189 
190         /**
191          * @deprecated Call getProtocolOfURL() instead
192          */
193         public static String getFileProtocol(String url)
194         {
195                 return getProtocolOfURL(url);
196         }
197 
198         /**
199          * Returns the protocol specified by a URL.
200          * @param url The URL
201          * @since jEdit 2.6pre5
202          */
203         public static String getProtocolOfURL(String url)
204         {
205                 return url.substring(0,url.indexOf(':'));
206         }
207 
208         /**
209          * Checks if the specified string is a URL.
210          * @param str The string to check
211          * @return True if the string is a URL, false otherwise
212          */
213         public static boolean isURL(String str)
214         {
215                 int fsIndex = Math.max(str.indexOf(File.separatorChar),
216                         str.indexOf('/'));
217                 if(fsIndex == 0) // /etc/passwd
218                         return false;
219                 else if(fsIndex == 2) // C:\AUTOEXEC.BAT
220                         return false;
221 
222                 int cIndex = str.indexOf(':');
223                 if(cIndex <= 1) // D:\WINDOWS
224                         return false;
225                 else if(fsIndex != -1 && cIndex > fsIndex) // /tmp/RTF::read.pm
226                         return false;
227 
228                 return true;
229         }
230 
231         /**
232          * Returns the number of leading white space characters in the
233          * specified string.
234          * @param str The string
235          */
236         public static int getLeadingWhiteSpace(String str)
237         {
238                 int whitespace = 0;
239 loop:    for(;whitespace < str.length();)
240                 {
241                         switch(str.charAt(whitespace))
242                         {
243                         case ' ': case '\t':
244                                 whitespace++;
245                                 break;
246                         default:
247                                 break loop;
248                         }
249                 }
250                 return whitespace;
251         }
252 
253         /**
254          * Returns the number of trailing whitespace characters in the
255          * specified string.
256          * @param str The string
257          * @since jEdit 2.5pre5
258          */
259         public static int getTrailingWhiteSpace(String str)
260         {
261                 int whitespace = 0;
262 loop:    for(int i = str.length() - 1; i >= 0; i--)
263                 {
264                         switch(str.charAt(i))
265                         {
266                         case ' ': case '\t':
267                                 whitespace++;
268                                 break;
269                         default:
270                                 break loop;
271                         }
272                 }
273                 return whitespace;
274         }
275 
276         /**
277          * Returns the width of the leading white space in the specified
278          * string.
279          * @param str The string
280          * @param tabSize The tab size
281          */
282         public static int getLeadingWhiteSpaceWidth(String str, int tabSize)
283         {
284                 int whitespace = 0;
285 loop:    for(int i = 0; i < str.length(); i++)
286                 {
287                         switch(str.charAt(i))
288                         {
289                         case ' ':
290                                 whitespace++;
291                                 break;
292                         case '\t':
293                                 whitespace += (tabSize - whitespace % tabSize);
294                                 break;
295                         default:
296                                 break loop;
297                         }
298                 }
299                 return whitespace;
300         }
301 
302         /**
303          * Creates a string of white space with the specified length.
304          * @param len The length
305          * @param tabSize The tab size, or 0 if tabs are not to be used
306          */
307         public static String createWhiteSpace(int len, int tabSize)
308         {
309                 StringBuffer buf = new StringBuffer();
310                 if(tabSize == 0)
311                 {
312                         while(len-- > 0)
313                                 buf.append(' ');
314                 }
315                 else
316                 {
317                         int count = len / tabSize;
318                         while(count-- > 0)
319                                 buf.append('\t');
320                         count = len % tabSize;
321                         while(count-- > 0)
322                                 buf.append(' ');
323                 }
324                 return buf.toString();
325         }
326 
327         /**
328          * Converts a Unix-style glob to a regular expression.
329          * ? becomes ., * becomes .*, {aa,bb} becomes (aa|bb).
330          * @param glob The glob pattern
331          */
332         public static String globToRE(String glob)
333         {
334                 StringBuffer buf = new StringBuffer();
335                 boolean backslash = false;
336                 boolean insideGroup = false;
337 
338                 for(int i = 0; i < glob.length(); i++)
339                 {
340                         char c = glob.charAt(i);
341                         if(backslash)
342                         {
343                                 buf.append('\\');
344                                 buf.append(c);
345                                 backslash = false;
346                                 continue;
347                         }
348 
349                         switch(c)
350                         {
351                         case '\\':
352                                 backslash = true;
353                                 break;
354                         case '?':
355                                 buf.append('.');
356                                 break;
357                         case '.':
358                                 buf.append("\\.");
359                                 break;
360                         case '*':
361                                 buf.append(".*");
362                                 break;
363                         case '{':
364                                 buf.append('(');
365                                 insideGroup = true;
366                                 break;
367                         case ',':
368                                 if(insideGroup)
369                                         buf.append('|');
370                                 else
371                                         buf.append(',');
372                                 break;
373                         case '}':
374                                 buf.append(')');
375                                 insideGroup = false;
376                                 break;
377                         default:
378                                 buf.append(c);
379                         }
380                 }
381 
382                 return buf.toString();
383         }
384 
385         /**
386          * Converts "\n" and "\t" escapes in the specified string to
387          * newlines and tabs.
388          * @param str The string
389          * @since jEdit 2.3pre1
390          */
391         public static String escapesToChars(String str)
392         {
393                 StringBuffer buf = new StringBuffer();
394                 for(int i = 0; i < str.length(); i++)
395                 {
396                         char c = str.charAt(i);
397                         switch(c)
398                         {
399                         case '\\':
400                                 if(i == str.length() - 1)
401                                 {
402                                         buf.append('\\');
403                                         break;
404                                 }
405                                 c = str.charAt(++i);
406                                 switch(c)
407                                 {
408                                 case 'n':
409                                         buf.append('\n');
410                                         break;
411                                 case 't':
412                                         buf.append('\t');
413                                         break;
414                                 default:
415                                         buf.append(c);
416                                         break;
417                                 }
418                                 break;
419                         default:
420                                 buf.append(c);
421                         }
422                 }
423                 return buf.toString();
424         }
425 
426         /**
427          * Escapes newlines, tabs, backslashes, quotes in the specified
428          * string.
429          * @param str The string
430          * @since jEdit 2.3pre1
431          */
432         public static String charsToEscapes(String str)
433         {
434                 return charsToEscapes(str,false);
435         }
436 
437         /**
438          * Escapes newlines, tabs, backslashes, quotes in the specified
439          * string.
440          * @param str The string
441          * @param history jEdit history files require additional escaping
442          * @since jEdit 2.7pre2
443          */
444         public static String charsToEscapes(String str, boolean history)
445         {
446                 StringBuffer buf = new StringBuffer();
447                 for(int i = 0; i < str.length(); i++)
448                 {
449                         char c = str.charAt(i);
450                         switch(c)
451                         {
452                         case '\n':
453                                 buf.append("\\n");
454                                 break;
455                         case '\t':
456                                 buf.append("\\t");
457                                 break;
458                         case '[':
459                                 if(history)
460                                         buf.append("\\[");
461                                 else
462                                         buf.append(c);
463                                 break;
464                         case ']':
465                                 if(history)
466                                         buf.append("\\]");
467                                 else
468                                         buf.append(c);
469                                 break;
470                         case '"':
471                                 if(history)
472                                         buf.append(c);
473                                 else
474                                         buf.append("\\\"");
475                                 break;
476                         case '\'':
477                                 if(history)
478                                         buf.append(c);
479                                 else
480                                         buf.append("\\\'");
481                                 break;
482                         case '\\':
483                                 buf.append("\\\\");
484                                 break;
485                         default:
486                                 buf.append(c);
487                                 break;
488                         }
489                 }
490                 return buf.toString();
491         }
492 
493         /**
494          * Sorts the specified array.
495          * @param obj The array
496          * @param compare Compares the objects
497          */
498         public static void quicksort(Object[] obj, Compare compare)
499         {
500                 if(obj.length == 0)
501                         return;
502 
503                 quicksort(obj,0,obj.length - 1,compare);
504         }
505 
506         /**
507          * Sorts the specified vector.
508          * @param vector The vector
509          * @param compare Compares the objects
510          */
511         public static void quicksort(Vector vector, Compare compare)
512         {
513                 if(vector.size() == 0)
514                         return;
515 
516                 quicksort(vector,0,vector.size() - 1,compare);
517         }
518 
519         /**
520          * An interface for comparing objects.
521          */
522         public interface Compare
523         {
524                 int compare(Object obj1, Object obj2);
525         }
526 
527         /**
528          * Compares strings.
529          */
530         public static class StringCompare implements Compare
531         {
532                 public int compare(Object obj1, Object obj2)
533                 {
534                         return obj1.toString().compareTo(obj2.toString());
535                 }
536         }
537 
538         /**
539          * Compares strings ignoring case.
540          */
541         public static class StringICaseCompare implements Compare
542         {
543                 public int compare(Object obj1, Object obj2)
544                 {
545                         return obj1.toString().toLowerCase()
546                                 .compareTo(obj2.toString()
547                                 .toLowerCase());
548                 }
549         }
550 
551         public static class MenuItemCompare implements Compare
552         {
553                 public int compare(Object obj1, Object obj2)
554                 {
555                         return ((JMenuItem)obj1).getText().compareTo(
556                                 ((JMenuItem)obj2).getText());
557                 }
558         }
559 
560         /**
561          * Compares two version strings formatted like 'xxx.xx.xxx'.
562          * The versions string are tokenized at '.' and the tokens
563          * are compared with each other one by one.
564          * For each substring they are compared as Integers first
565          * and if that fails, as Strings. The comparison ends with
566          * the first difference.
567          * Note, that "1.2.0" &lt; "1.2.0pre1", because "0" &lt; "0pre1".
568          * Therefore you should avoid mixing numbers and text.
569          * All string comparisons are case sensitive.
570          */
571         public static class VersionCompare implements Compare
572         {
573                 /**
574                  * compare two version strings
575                  * @param obj1 first version. Should be a String.
576                  * @param obj2 secons version. Should be a String.
577                  * @return a negative value, if <code>obj1 < obj2</code>,
578                  *         a positive value, if <code>obj1 > obj2</code>,
579                  *         0, if <code>obj1.equals(obj2)</code>.
580                  */
581                 public int compare(Object obj1, Object obj2)
582                 {
583                         String v1 = obj1.toString();
584                         String v2 = obj2.toString();
585                         StringTokenizer vt1 = new StringTokenizer(v1,".");
586                         StringTokenizer vt2 = new StringTokenizer(v2,".");
587                         int comp = 0;
588 
589                         while(vt1.hasMoreTokens() && vt2.hasMoreTokens()) {
590                                 String vt1tok = vt1.nextToken();
591                                 String vt2tok = vt2.nextToken();
592                                 try
593                                 {
594                                         int i1 = Integer.parseInt(vt1tok);
595                                         int i2 = Integer.parseInt(vt2tok);
596                                         comp = i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
597                                 }
598                                 catch(NumberFormatException e)
599                                 {
600                                         comp = vt1tok.compareTo(vt2tok);
601                                 }
602                                 if(comp != 0)
603                                         return comp;
604                         }
605 
606                         return vt1.hasMoreTokens() ? 1
607                                 : vt2.hasMoreTokens() ? -1 : 0;
608                 }
609         }
610 
611         /**
612          * Helper function to compare two version strings, using the
613          * VersionCompare class.
614          * @param version1 the first version string
615          * @param version2 the second version string
616          * @return a negative value, if <code>version1 &lt; version2</code>,
617          *         a positive value, if <code>version1 &gt; version2</code>,
618          *         0, if <code>version1.equals(version2)</code>.
619          */
620         public static int compareVersions(String version1, String version2)
621         {
622                 VersionCompare comparator = new VersionCompare();
623                 return comparator.compare(version1,version2);
624         }
625 
626         /**
627          * Converts an internal version number (build) into a
628          * `human-readable' form.
629          * @param build The build
630          */
631         public static String buildToVersion(String build)
632         {
633                 if(build.length() != 11)
634                         return "<unknown version: " + build + ">";
635                 // First 2 chars are the major version number
636                 int major = Integer.parseInt(build.substring(0,2));
637                 // Second 2 are the minor number
638                 int minor = Integer.parseInt(build.substring(3,5));
639                 // Then the pre-release status
640                 int beta = Integer.parseInt(build.substring(6,8));
641                 // Finally the bug fix release
642                 int bugfix = Integer.parseInt(build.substring(9,11));
643 
644                 return "" + major + "." + minor
645                         + (beta != 99 ? "pre" + beta :
646                         (bugfix != 0 ? "." + bugfix : "final"));
647         }
648 
649         // private members
650         private Misc() {}
651 
652         private static String canonPath(String path)
653         {
654                 if(File.separatorChar == '\\')
655                 {
656                         // get rid of mixed paths on Windows
657                         path = path.replace('/','\\');
658                 }
659 
660                 try
661                 {
662                         return new File(path).getCanonicalPath();
663                 }
664                 catch(Exception e)
665                 {
666                         return path;
667                 }
668         }
669 
670         private static void quicksort(Object[] obj, int _start, int _end,
671                 Compare compare)
672         {
673                 int start = _start;
674                 int end = _end;
675 
676                 Object mid = obj[(_start + _end) / 2];
677 
678                 if(_start > _end)
679                         return;
680 
681                 while(start <= end)
682                 {
683                         while((start < _end) && (compare.compare(obj[start],mid) < 0))
684                                 start++;
685 
686                         while((end > _start) && (compare.compare(obj[end],mid) > 0))
687                                 end--;
688 
689                         if(start <= end)
690                         {
691                                 Object o = obj[start];
692                                 obj[start] = obj[end];
693                                 obj[end] = o;
694 
695                                 start++;
696                                 end--;
697                         }
698                 }
699 
700                 if(_start < end)
701                         quicksort(obj,_start,end,compare);
702 
703                 if(start < _end)
704                         quicksort(obj,start,_end,compare);
705         }
706 
707         private static void quicksort(Vector obj, int _start, int _end,
708                 Compare compare)
709         {
710                 int start = _start;
711                 int end = _end;
712 
713                 Object mid = obj.elementAt((_start + _end) / 2);
714 
715                 if(_start > _end)
716                         return;
717 
718                 while(start <= end)
719                 {
720                         while((start < _end) && (compare.compare(obj.elementAt(start),mid) < 0))
721                                 start++;
722 
723                         while((end > _start) && (compare.compare(obj.elementAt(end),mid) > 0))
724                                 end--;
725 
726                         if(start <= end)
727                         {
728                                 Object o = obj.elementAt(start);
729                                 obj.setElementAt(obj.elementAt(end),start);
730                                 obj.setElementAt(o,end);
731 
732                                 start++;
733                                 end--;
734                         }
735                 }
736 
737                 if(_start < end)
738                         quicksort(obj,_start,end,compare);
739 
740                 if(start < _end)
741                         quicksort(obj,start,_end,compare);
742         }
743 }