PageRenderTime 24ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/jedit-4.3.2/jEdit/org/gjt/sp/util/StandardUtilities.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 710 lines | 442 code | 56 blank | 212 comment | 104 complexity | 29d0e84f95c09e1272e82de93940f623 MD5 | raw file
  1. /*
  2. * StandardUtilities.java - Various miscallaneous utility functions
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1999, 2006 Matthieu Casanova, Slava Pestov
  7. * Portions copyright (C) 2000 Richard S. Hall
  8. * Portions copyright (C) 2001 Dirk Moebius
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23. */
  24. package org.gjt.sp.util;
  25. //{{{ Imports
  26. import javax.swing.text.Segment;
  27. import java.util.Comparator;
  28. import java.util.Stack;
  29. //}}}
  30. /**
  31. * Several tools that depends on JDK only.
  32. *
  33. * @author Matthieu Casanova
  34. * @version $Id: StandardUtilities.java 14923 2009-04-13 18:40:55Z shlomy $
  35. * @since 4.3pre5
  36. */
  37. public class StandardUtilities
  38. {
  39. //{{{ Text methods
  40. //{{{ charsToEscapes() method
  41. /**
  42. * Escapes newlines, tabs, backslashes, and quotes in the specified
  43. * string.
  44. * @param str The string
  45. * @since jEdit 4.3pre15
  46. */
  47. public static String charsToEscapes(String str)
  48. {
  49. return charsToEscapes(str,"\n\t\\\"'");
  50. } //}}}
  51. //{{{ charsToEscapes() method
  52. /**
  53. * Escapes the specified characters in the specified string.
  54. * @param str The string
  55. * @param toEscape Any characters that require escaping
  56. * @since jEdit 4.3pre15
  57. */
  58. public static String charsToEscapes(String str, String toEscape)
  59. {
  60. StringBuilder buf = new StringBuilder();
  61. for(int i = 0; i < str.length(); i++)
  62. {
  63. char c = str.charAt(i);
  64. if(toEscape.indexOf(c) != -1)
  65. {
  66. if(c == '\n')
  67. buf.append("\\n");
  68. else if(c == '\t')
  69. buf.append("\\t");
  70. else
  71. {
  72. buf.append('\\');
  73. buf.append(c);
  74. }
  75. }
  76. else
  77. buf.append(c);
  78. }
  79. return buf.toString();
  80. } //}}}
  81. //{{{ getPrevIndentStyle() method
  82. /**
  83. * @param str A java string
  84. * @return the leading whitespace of that string, for indenting subsequent lines.
  85. * @since jEdit 4.3pre10
  86. */
  87. public static String getIndentString(String str)
  88. {
  89. StringBuilder indentString = new StringBuilder();
  90. for (int i = 0; i < str.length(); i++)
  91. {
  92. char ch = str.charAt(i);
  93. if (! Character.isWhitespace(ch))
  94. break;
  95. indentString.append(ch);
  96. }
  97. return indentString.toString();
  98. } //}}}
  99. //{{{ getLeadingWhiteSpace() method
  100. /**
  101. * Returns the number of leading white space characters in the
  102. * specified string.
  103. *
  104. * @param str The string
  105. */
  106. public static int getLeadingWhiteSpace(String str)
  107. {
  108. return getLeadingWhiteSpace((CharSequence)str);
  109. } //}}}
  110. //{{{ getLeadingWhiteSpace() method
  111. /**
  112. * Returns the number of leading white space characters in the
  113. * specified string.
  114. *
  115. * @param str The string
  116. * @since jEdit 4.3pre15
  117. */
  118. public static int getLeadingWhiteSpace(CharSequence str)
  119. {
  120. int whitespace = 0;
  121. loop: for(;whitespace < str.length();)
  122. {
  123. switch(str.charAt(whitespace))
  124. {
  125. case ' ':
  126. case '\t':
  127. whitespace++;
  128. break;
  129. default:
  130. break loop;
  131. }
  132. }
  133. return whitespace;
  134. } //}}}
  135. //{{{ getTrailingWhiteSpace() method
  136. /**
  137. * Returns the number of trailing whitespace characters in the
  138. * specified string.
  139. * @param str The string
  140. */
  141. public static int getTrailingWhiteSpace(String str)
  142. {
  143. int whitespace = 0;
  144. loop: for(int i = str.length() - 1; i >= 0; i--)
  145. {
  146. switch(str.charAt(i))
  147. {
  148. case ' ':
  149. case '\t':
  150. whitespace++;
  151. break;
  152. default:
  153. break loop;
  154. }
  155. }
  156. return whitespace;
  157. } //}}}
  158. //{{{ getLeadingWhiteSpaceWidth() method
  159. /**
  160. * Returns the width of the leading white space in the specified
  161. * string.
  162. * @param str The string
  163. * @param tabSize The tab size
  164. */
  165. public static int getLeadingWhiteSpaceWidth(String str, int tabSize)
  166. {
  167. return getLeadingWhiteSpaceWidth((CharSequence)str, tabSize);
  168. } //}}}
  169. //{{{ getLeadingWhiteSpaceWidth() method
  170. /**
  171. * Returns the width of the leading white space in the specified
  172. * string.
  173. * @param str The string
  174. * @param tabSize The tab size
  175. * @since jEdit 4.3pre15
  176. */
  177. public static int getLeadingWhiteSpaceWidth(CharSequence str, int tabSize)
  178. {
  179. int whitespace = 0;
  180. loop: for(int i = 0; i < str.length(); i++)
  181. {
  182. switch(str.charAt(i))
  183. {
  184. case ' ':
  185. whitespace++;
  186. break;
  187. case '\t':
  188. whitespace += tabSize -
  189. whitespace % tabSize;
  190. break;
  191. default:
  192. break loop;
  193. }
  194. }
  195. return whitespace;
  196. } //}}}
  197. //{{{ createWhiteSpace() method
  198. /**
  199. * Creates a string of white space with the specified length.<p>
  200. *
  201. * To get a whitespace string tuned to the current buffer's
  202. * settings, call this method as follows:
  203. *
  204. * <pre>myWhitespace = MiscUtilities.createWhiteSpace(myLength,
  205. * (buffer.getBooleanProperty("noTabs") ? 0
  206. * : buffer.getTabSize()));</pre>
  207. *
  208. * @param len The length
  209. * @param tabSize The tab size, or 0 if tabs are not to be used
  210. */
  211. public static String createWhiteSpace(int len, int tabSize)
  212. {
  213. return createWhiteSpace(len,tabSize,0);
  214. } //}}}
  215. //{{{ truncateWhiteSpace() method
  216. public static String truncateWhiteSpace(int len, int tabSize,
  217. String indentStr)
  218. {
  219. StringBuilder buf = new StringBuilder();
  220. int indent = 0;
  221. for (int i = 0; indent < len && i < indentStr.length(); i++)
  222. {
  223. char c = indentStr.charAt(i);
  224. if (c == ' ')
  225. {
  226. indent++;
  227. buf.append(c);
  228. }
  229. else if (c == '\t')
  230. {
  231. int withTab = indent + tabSize - (indent % tabSize);
  232. if (withTab > len)
  233. {
  234. for (; indent < len; indent++)
  235. buf.append(' ');
  236. }
  237. else
  238. {
  239. indent = withTab;
  240. buf.append(c);
  241. }
  242. }
  243. }
  244. return buf.toString();
  245. } //}}}
  246. //{{{ createWhiteSpace() method
  247. /**
  248. * Creates a string of white space with the specified length.<p>
  249. *
  250. * To get a whitespace string tuned to the current buffer's
  251. * settings, call this method as follows:
  252. *
  253. * <pre>myWhitespace = MiscUtilities.createWhiteSpace(myLength,
  254. * (buffer.getBooleanProperty("noTabs") ? 0
  255. * : buffer.getTabSize()));</pre>
  256. *
  257. * @param len The length
  258. * @param tabSize The tab size, or 0 if tabs are not to be used
  259. * @param start The start offset, for tab alignment
  260. */
  261. public static String createWhiteSpace(int len, int tabSize, int start)
  262. {
  263. StringBuilder buf = new StringBuilder();
  264. if(tabSize == 0)
  265. {
  266. while(len-- > 0)
  267. buf.append(' ');
  268. }
  269. else if(len == 1)
  270. buf.append(' ');
  271. else
  272. {
  273. int count = (len + start % tabSize) / tabSize;
  274. if(count != 0)
  275. len += start;
  276. while(count-- > 0)
  277. buf.append('\t');
  278. count = len % tabSize;
  279. while(count-- > 0)
  280. buf.append(' ');
  281. }
  282. return buf.toString();
  283. } //}}}
  284. //{{{ getVirtualWidth() method
  285. /**
  286. * Returns the virtual column number (taking tabs into account) of the
  287. * specified offset in the segment.
  288. *
  289. * @param seg The segment
  290. * @param tabSize The tab size
  291. */
  292. public static int getVirtualWidth(Segment seg, int tabSize)
  293. {
  294. int virtualPosition = 0;
  295. for (int i = 0; i < seg.count; i++)
  296. {
  297. char ch = seg.array[seg.offset + i];
  298. if (ch == '\t')
  299. {
  300. virtualPosition += tabSize
  301. - virtualPosition % tabSize;
  302. }
  303. else
  304. {
  305. ++virtualPosition;
  306. }
  307. }
  308. return virtualPosition;
  309. } //}}}
  310. //{{{ getOffsetOfVirtualColumn() method
  311. /**
  312. * Returns the array offset of a virtual column number (taking tabs
  313. * into account) in the segment.
  314. *
  315. * @param seg The segment
  316. * @param tabSize The tab size
  317. * @param column The virtual column number
  318. * @param totalVirtualWidth If this array is non-null, the total
  319. * virtual width will be stored in its first location if this method
  320. * returns -1.
  321. *
  322. * @return -1 if the column is out of bounds
  323. */
  324. public static int getOffsetOfVirtualColumn(Segment seg, int tabSize,
  325. int column, int[] totalVirtualWidth)
  326. {
  327. int virtualPosition = 0;
  328. for (int i = 0; i < seg.count; i++)
  329. {
  330. char ch = seg.array[seg.offset + i];
  331. if (ch == '\t')
  332. {
  333. int tabWidth = tabSize
  334. - virtualPosition % tabSize;
  335. if(virtualPosition >= column)
  336. return i;
  337. else
  338. virtualPosition += tabWidth;
  339. }
  340. else
  341. {
  342. if(virtualPosition >= column)
  343. return i;
  344. else
  345. ++virtualPosition;
  346. }
  347. }
  348. if(totalVirtualWidth != null)
  349. totalVirtualWidth[0] = virtualPosition;
  350. return -1;
  351. } //}}}
  352. //{{{ compareStrings() method
  353. /**
  354. * Compares two strings.<p>
  355. *
  356. * Unlike <function>String.compareTo()</function>,
  357. * this method correctly recognizes and handles embedded numbers.
  358. * For example, it places "My file 2" before "My file 10".<p>
  359. *
  360. * @param str1 The first string
  361. * @param str2 The second string
  362. * @param ignoreCase If true, case will be ignored
  363. * @return negative If str1 &lt; str2, 0 if both are the same,
  364. * positive if str1 &gt; str2
  365. * @since jEdit 4.3pre5
  366. */
  367. public static int compareStrings(String str1, String str2, boolean ignoreCase)
  368. {
  369. char[] char1 = str1.toCharArray();
  370. char[] char2 = str2.toCharArray();
  371. int len = Math.min(char1.length,char2.length);
  372. for(int i = 0, j = 0; i < len && j < len; i++, j++)
  373. {
  374. char ch1 = char1[i];
  375. char ch2 = char2[j];
  376. if(Character.isDigit(ch1) && Character.isDigit(ch2)
  377. && ch1 != '0' && ch2 != '0')
  378. {
  379. int _i = i + 1;
  380. int _j = j + 1;
  381. for(; _i < char1.length; _i++)
  382. {
  383. if(!Character.isDigit(char1[_i]))
  384. {
  385. //_i--;
  386. break;
  387. }
  388. }
  389. for(; _j < char2.length; _j++)
  390. {
  391. if(!Character.isDigit(char2[_j]))
  392. {
  393. //_j--;
  394. break;
  395. }
  396. }
  397. int len1 = _i - i;
  398. int len2 = _j - j;
  399. if(len1 > len2)
  400. return 1;
  401. else if(len1 < len2)
  402. return -1;
  403. else
  404. {
  405. for(int k = 0; k < len1; k++)
  406. {
  407. ch1 = char1[i + k];
  408. ch2 = char2[j + k];
  409. if(ch1 != ch2)
  410. return ch1 - ch2;
  411. }
  412. }
  413. i = _i - 1;
  414. j = _j - 1;
  415. }
  416. else
  417. {
  418. if(ignoreCase)
  419. {
  420. ch1 = Character.toLowerCase(ch1);
  421. ch2 = Character.toLowerCase(ch2);
  422. }
  423. if(ch1 != ch2)
  424. return ch1 - ch2;
  425. }
  426. }
  427. return char1.length - char2.length;
  428. } //}}}
  429. //{{{ StringCompare class
  430. /**
  431. * Compares objects as strings.
  432. */
  433. public static class StringCompare<E> implements Comparator<E>
  434. {
  435. private boolean icase;
  436. public StringCompare(boolean icase)
  437. {
  438. this.icase = icase;
  439. }
  440. public StringCompare()
  441. {
  442. }
  443. public int compare(E obj1, E obj2)
  444. {
  445. return compareStrings(obj1.toString(),
  446. obj2.toString(),icase);
  447. }
  448. } //}}}
  449. //{{{ objectsEqual() method
  450. /**
  451. * Returns if two strings are equal. This correctly handles null pointers,
  452. * as opposed to calling <code>o1.equals(o2)</code>.
  453. * @since jEdit 4.3pre6
  454. */
  455. public static boolean objectsEqual(Object o1, Object o2)
  456. {
  457. if(o1 == null)
  458. {
  459. if(o2 == null)
  460. return true;
  461. else
  462. return false;
  463. }
  464. else if(o2 == null)
  465. return false;
  466. else
  467. return o1.equals(o2);
  468. } //}}}
  469. //{{{ globToRE() method
  470. /**
  471. * Converts a Unix-style glob to a regular expression.<p>
  472. *
  473. * ? becomes ., * becomes .*, {aa,bb} becomes (aa|bb).
  474. * @param glob The glob pattern
  475. * @since jEdit 4.3pre7
  476. */
  477. public static String globToRE(String glob)
  478. {
  479. if (glob.startsWith("(re)"))
  480. {
  481. return glob.substring(4);
  482. }
  483. final Object NEG = new Object();
  484. final Object GROUP = new Object();
  485. Stack<Object> state = new Stack<Object>();
  486. StringBuilder buf = new StringBuilder();
  487. boolean backslash = false;
  488. for(int i = 0; i < glob.length(); i++)
  489. {
  490. char c = glob.charAt(i);
  491. if(backslash)
  492. {
  493. buf.append('\\');
  494. buf.append(c);
  495. backslash = false;
  496. continue;
  497. }
  498. switch(c)
  499. {
  500. case '\\':
  501. backslash = true;
  502. break;
  503. case '?':
  504. buf.append('.');
  505. break;
  506. case '.':
  507. case '+':
  508. case '(':
  509. case ')':
  510. buf.append('\\');
  511. buf.append(c);
  512. break;
  513. case '*':
  514. buf.append(".*");
  515. break;
  516. case '|':
  517. if(backslash)
  518. buf.append("\\|");
  519. else
  520. buf.append('|');
  521. break;
  522. case '{':
  523. buf.append('(');
  524. if(i + 1 != glob.length() && glob.charAt(i + 1) == '!')
  525. {
  526. buf.append('?');
  527. state.push(NEG);
  528. }
  529. else
  530. state.push(GROUP);
  531. break;
  532. case ',':
  533. if(!state.isEmpty() && state.peek() == GROUP)
  534. buf.append('|');
  535. else
  536. buf.append(',');
  537. break;
  538. case '}':
  539. if(!state.isEmpty())
  540. {
  541. buf.append(')');
  542. if(state.pop() == NEG)
  543. buf.append(".*");
  544. }
  545. else
  546. buf.append('}');
  547. break;
  548. default:
  549. buf.append(c);
  550. }
  551. }
  552. return buf.toString();
  553. } //}}}
  554. //{{{ regionMatches() method
  555. /**
  556. * Implementation of String.regionMatches() for CharSequence.
  557. *
  558. * @param seq The test CharSequence.
  559. * @param toff Offset for the test sequence.
  560. * @param other The sequence to compare to.
  561. * @param ooff Offset of the comparison sequence.
  562. * @param len How many characters to compare.
  563. * @return Whether the two subsequences are equal.
  564. * @see String#regionMatches(int,String,int,int)
  565. *
  566. * @since jEdit 4.3pre15
  567. */
  568. public static boolean regionMatches(CharSequence seq,
  569. int toff,
  570. CharSequence other,
  571. int ooff,
  572. int len)
  573. {
  574. if (toff < 0 || ooff < 0 || len < 0)
  575. return false;
  576. boolean ret = true;
  577. for (int i = 0; i < len; i++)
  578. {
  579. char c1;
  580. if (i + toff < seq.length())
  581. c1 = seq.charAt(i + toff);
  582. else
  583. {
  584. ret = false;
  585. break;
  586. }
  587. char c2;
  588. if (i + ooff < other.length())
  589. c2 = other.charAt(i + ooff);
  590. else
  591. {
  592. ret = false;
  593. break;
  594. }
  595. if (c1 != c2)
  596. {
  597. ret = false;
  598. break;
  599. }
  600. }
  601. return ret;
  602. } //}}}
  603. //{{{ startsWith() method
  604. /**
  605. * Implementation of String.startsWith() for CharSequence.
  606. *
  607. * @param seq The CharSequence.
  608. * @param str String to test.
  609. * @return Whether the sequence starts with the test string.
  610. *
  611. * @since jEdit 4.3pre15
  612. */
  613. public static boolean startsWith(CharSequence seq, String str)
  614. {
  615. boolean ret = true;
  616. for (int i = 0; i < str.length(); i++)
  617. {
  618. if (i >= seq.length() ||
  619. seq.charAt(i) != str.charAt(i))
  620. {
  621. ret = false;
  622. break;
  623. }
  624. }
  625. return ret;
  626. } //}}}
  627. //{{{ getBoolean() method
  628. /**
  629. * Returns a boolean from a given object.
  630. * @param obj the object
  631. * @param def The default value
  632. * @return the boolean value if obj is a Boolean,
  633. * true if the value is "true", "yes", "on",
  634. * false if the value is "false", "no", "off"
  635. * def if the value is null or anything else
  636. * @since jEdit 4.3pre17
  637. */
  638. public static boolean getBoolean(Object obj, boolean def)
  639. {
  640. if(obj == null)
  641. return def;
  642. else if(obj instanceof Boolean)
  643. return ((Boolean)obj).booleanValue();
  644. else if("true".equals(obj) || "yes".equals(obj)
  645. || "on".equals(obj))
  646. return true;
  647. else if("false".equals(obj) || "no".equals(obj)
  648. || "off".equals(obj))
  649. return false;
  650. return def;
  651. } //}}}
  652. //}}}
  653. private StandardUtilities(){}
  654. }