1. /*
  2. * @(#)String.java 1.115 01/11/29
  3. *
  4. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.lang;
  8. import java.util.Hashtable;
  9. import java.util.Locale;
  10. import java.util.Comparator;
  11. import sun.io.ByteToCharConverter;
  12. import sun.io.CharToByteConverter;
  13. import java.io.CharConversionException;
  14. import java.io.UnsupportedEncodingException;
  15. import java.io.ObjectStreamClass;
  16. import java.io.ObjectStreamField;
  17. import java.lang.ref.SoftReference;
  18. /**
  19. * The <code>String</code> class represents character strings. All
  20. * string literals in Java programs, such as <code>"abc"</code>, are
  21. * implemented as instances of this class.
  22. * <p>
  23. * Strings are constant; their values cannot be changed after they
  24. * are created. String buffers support mutable strings.
  25. * Because String objects are immutable they can be shared. For example:
  26. * <p><blockquote><pre>
  27. * String str = "abc";
  28. * </pre></blockquote><p>
  29. * is equivalent to:
  30. * <p><blockquote><pre>
  31. * char data[] = {'a', 'b', 'c'};
  32. * String str = new String(data);
  33. * </pre></blockquote><p>
  34. * Here are some more examples of how strings can be used:
  35. * <p><blockquote><pre>
  36. * System.out.println("abc");
  37. * String cde = "cde";
  38. * System.out.println("abc" + cde);
  39. * String c = "abc".substring(2,3);
  40. * String d = cde.substring(1, 2);
  41. * </pre></blockquote>
  42. * <p>
  43. * The class <code>String</code> includes methods for examining
  44. * individual characters of the sequence, for comparing strings, for
  45. * searching strings, for extracting substrings, and for creating a
  46. * copy of a string with all characters translated to uppercase or to
  47. * lowercase.
  48. * <p>
  49. * The Java language provides special support for the string
  50. * concatentation operator ( + ), and for conversion of
  51. * other objects to strings. String concatenation is implemented
  52. * through the <code>StringBuffer</code> class and its
  53. * <code>append</code> method.
  54. * String conversions are implemented through the method
  55. * <code>toString</code>, defined by <code>Object</code> and
  56. * inherited by all classes in Java. For additional information on
  57. * string concatenation and conversion, see Gosling, Joy, and Steele,
  58. * <i>The Java Language Specification</i>.
  59. *
  60. * @author Lee Boynton
  61. * @author Arthur van Hoff
  62. * @version 1.115, 11/29/01
  63. * @see java.lang.Object#toString()
  64. * @see java.lang.StringBuffer
  65. * @see java.lang.StringBuffer#append(boolean)
  66. * @see java.lang.StringBuffer#append(char)
  67. * @see java.lang.StringBuffer#append(char[])
  68. * @see java.lang.StringBuffer#append(char[], int, int)
  69. * @see java.lang.StringBuffer#append(double)
  70. * @see java.lang.StringBuffer#append(float)
  71. * @see java.lang.StringBuffer#append(int)
  72. * @see java.lang.StringBuffer#append(long)
  73. * @see java.lang.StringBuffer#append(java.lang.Object)
  74. * @see java.lang.StringBuffer#append(java.lang.String)
  75. * @since JDK1.0
  76. */
  77. public final
  78. class String implements java.io.Serializable, Comparable {
  79. /** The value is used for character storage. */
  80. private char value[];
  81. /** The offset is the first index of the storage that is used. */
  82. private int offset;
  83. /** The count is the number of characters in the String. */
  84. private int count;
  85. /** The cached converter for each thread.
  86. * Note: These are declared null to minimize the classes
  87. * that String must depend on during initialization
  88. */
  89. private static ThreadLocal btcConverter = null;
  90. private static ThreadLocal ctbConverter = null;
  91. /**
  92. * Returns a <code>ByteToCharConverter</code> that uses the specified
  93. * encoding. For efficiency a cache is maintained that holds the last
  94. * used converter.
  95. *
  96. * @param enc The name of a character encoding
  97. * @return ByteToCharConverter for the specified encoding.
  98. * @exception UnsupportedEncodingException
  99. * If the named encoding is not supported
  100. * @since JDK1.2
  101. */
  102. private static ByteToCharConverter getBTCConverter(String encoding)
  103. throws UnsupportedEncodingException {
  104. ByteToCharConverter btc = null;
  105. if (btcConverter == null)
  106. btcConverter = new ThreadLocal();
  107. SoftReference ref = (SoftReference)(btcConverter.get());
  108. if (ref==null || (btc = (ByteToCharConverter)ref.get())==null ||
  109. !encoding.equals(btc.getCharacterEncoding())) {
  110. btc = ByteToCharConverter.getConverter(encoding);
  111. btcConverter.set(new SoftReference(btc));
  112. } else {
  113. btc.reset();
  114. }
  115. return btc;
  116. }
  117. /**
  118. * Returns a <code>CharToByteConverter</code> that uses the specified
  119. * encoding. For efficiency a cache is maintained that holds the last
  120. * used converter.
  121. *
  122. * @param enc The name of a character encoding
  123. * @return CharToByteConverter for the specified encoding.
  124. * @exception UnsupportedEncodingException
  125. * If the named encoding is not supported
  126. * @since JDK1.2
  127. */
  128. private static CharToByteConverter getCTBConverter(String encoding)
  129. throws UnsupportedEncodingException {
  130. CharToByteConverter ctb = null;
  131. if (ctbConverter == null)
  132. ctbConverter = new ThreadLocal();
  133. SoftReference ref = (SoftReference)(ctbConverter.get());
  134. if (ref==null || (ctb = (CharToByteConverter)ref.get())==null ||
  135. !encoding.equals(ctb.getCharacterEncoding())) {
  136. ctb = CharToByteConverter.getConverter(encoding);
  137. ctbConverter.set(new SoftReference(ctb));
  138. } else {
  139. ctb.reset();
  140. }
  141. return ctb;
  142. }
  143. /** use serialVersionUID from JDK 1.0.2 for interoperability */
  144. private static final long serialVersionUID = -6849794470754667710L;
  145. /**
  146. * Class String is special cased within the Serialization Stream Protocol.
  147. *
  148. * A String instance is written intially into an ObjectOutputStream in the
  149. * following format:
  150. * <pre>
  151. * <code>TC_STRING</code> (utf String)
  152. * </pre>
  153. * The String is written by method <code>DataOutput.writeUTF</code>.
  154. * A new handle is generated to refer to all future references to the
  155. * string instance within the stream.
  156. */
  157. private static final ObjectStreamField[] serialPersistentFields =
  158. ObjectStreamClass.NO_FIELDS;
  159. /**
  160. * Initializes a newly created <code>String</code> object so that it
  161. * represents an empty character sequence.
  162. */
  163. public String() {
  164. value = new char[0];
  165. }
  166. /**
  167. * Initializes a newly created <code>String</code> object so that it
  168. * represents the same sequence of characters as the argument; in other
  169. * words, the newly created string is a copy of the argument string.
  170. *
  171. * @param value a <code>String</code>.
  172. */
  173. public String(String value) {
  174. count = value.length();
  175. this.value = new char[count];
  176. value.getChars(0, count, this.value, 0);
  177. }
  178. /**
  179. * Allocates a new <code>String</code> so that it represents the
  180. * sequence of characters currently contained in the character array
  181. * argument. The contents of the character array are copied; subsequent
  182. * modification of the character array does not affect the newly created
  183. * string.
  184. *
  185. * @param value the initial value of the string.
  186. * @throws NullPointerException if <code>value</code> is <code>null</code>.
  187. */
  188. public String(char value[]) {
  189. this.count = value.length;
  190. this.value = new char[count];
  191. System.arraycopy(value, 0, this.value, 0, count);
  192. }
  193. /**
  194. * Allocates a new <code>String</code> that contains characters from
  195. * a subarray of the character array argument. The <code>offset</code>
  196. * argument is the index of the first character of the subarray and
  197. * the <code>count</code> argument specifies the length of the
  198. * subarray. The contents of the subarray are copied; subsequent
  199. * modification of the character array does not affect the newly
  200. * created string.
  201. *
  202. * @param value array that is the source of characters.
  203. * @param offset the initial offset.
  204. * @param count the length.
  205. * @exception IndexOutOfBoundsException if the <code>offset</code>
  206. * and <code>count</code> arguments index characters outside
  207. * the bounds of the <code>value</code> array.
  208. * @exception NullPointerException if <code>value</code> is
  209. * <code>null</code>.
  210. */
  211. public String(char value[], int offset, int count) {
  212. if (offset < 0) {
  213. throw new StringIndexOutOfBoundsException(offset);
  214. }
  215. if (count < 0) {
  216. throw new StringIndexOutOfBoundsException(count);
  217. }
  218. // Note: offset or count might be near -1>>>1.
  219. if (offset > value.length - count) {
  220. throw new StringIndexOutOfBoundsException(offset + count);
  221. }
  222. this.value = new char[count];
  223. this.count = count;
  224. System.arraycopy(value, offset, this.value, 0, count);
  225. }
  226. /**
  227. * Allocates a new <code>String</code> constructed from a subarray
  228. * of an array of 8-bit integer values.
  229. * <p>
  230. * The <code>offset</code> argument is the index of the first byte
  231. * of the subarray, and the <code>count</code> argument specifies the
  232. * length of the subarray.
  233. * <p>
  234. * Each <code>byte</code> in the subarray is converted to a
  235. * <code>char</code> as specified in the method above.
  236. *
  237. * @deprecated This method does not properly convert bytes into characters.
  238. * As of JDK 1.1, the preferred way to do this is via the
  239. * <code>String</code> constructors that take a character-encoding name or
  240. * that use the platform's default encoding.
  241. *
  242. * @param ascii the bytes to be converted to characters.
  243. * @param hibyte the top 8 bits of each 16-bit Unicode character.
  244. * @param offset the initial offset.
  245. * @param count the length.
  246. * @exception IndexOutOfBoundsException if the <code>offset</code>
  247. * or <code>count</code> argument is invalid.
  248. * @exception NullPointerException if <code>ascii</code> is
  249. * <code>null</code>.
  250. * @see java.lang.String#String(byte[], int)
  251. * @see java.lang.String#String(byte[], int, int, java.lang.String)
  252. * @see java.lang.String#String(byte[], int, int)
  253. * @see java.lang.String#String(byte[], java.lang.String)
  254. * @see java.lang.String#String(byte[])
  255. */
  256. public String(byte ascii[], int hibyte, int offset, int count) {
  257. if (offset < 0) {
  258. throw new StringIndexOutOfBoundsException(offset);
  259. }
  260. if (count < 0) {
  261. throw new StringIndexOutOfBoundsException(count);
  262. }
  263. // Note: offset or count might be near -1>>>1.
  264. if (offset > ascii.length - count) {
  265. throw new StringIndexOutOfBoundsException(offset + count);
  266. }
  267. char value[] = new char[count];
  268. this.count = count;
  269. this.value = value;
  270. if (hibyte == 0) {
  271. for (int i = count ; i-- > 0 ;) {
  272. value[i] = (char) (ascii[i + offset] & 0xff);
  273. }
  274. } else {
  275. hibyte <<= 8;
  276. for (int i = count ; i-- > 0 ;) {
  277. value[i] = (char) (hibyte | (ascii[i + offset] & 0xff));
  278. }
  279. }
  280. }
  281. /**
  282. * Allocates a new <code>String</code> containing characters
  283. * constructed from an array of 8-bit integer values. Each character
  284. * <i>c</i>in the resulting string is constructed from the
  285. * corresponding component <i>b</i> in the byte array such that:
  286. * <p><blockquote><pre>
  287. * <b><i>c</i></b> == (char)(((hibyte & 0xff) << 8)
  288. * | (<b><i>b</i></b> & 0xff))
  289. * </pre></blockquote>
  290. *
  291. * @deprecated This method does not properly convert bytes into characters.
  292. * As of JDK 1.1, the preferred way to do this is via the
  293. * <code>String</code> constructors that take a character-encoding name or
  294. * that use the platform's default encoding.
  295. *
  296. * @param ascii the bytes to be converted to characters.
  297. * @param hibyte the top 8 bits of each 16-bit Unicode character.
  298. * @exception NullPointerException If <code>ascii</code> is
  299. * <code>null</code>.
  300. * @see java.lang.String#String(byte[], int, int, java.lang.String)
  301. * @see java.lang.String#String(byte[], int, int)
  302. * @see java.lang.String#String(byte[], java.lang.String)
  303. * @see java.lang.String#String(byte[])
  304. */
  305. public String(byte ascii[], int hibyte) {
  306. this(ascii, hibyte, 0, ascii.length);
  307. }
  308. /**
  309. * Construct a new <code>String</code> by converting the specified
  310. * subarray of bytes using the specified character-encoding converter. The
  311. * length of the new <code>String</code> is a function of the encoding, and
  312. * hence may not be equal to the length of the subarray.
  313. *
  314. * @param bytes The bytes to be converted into characters
  315. * @param offset Index of the first byte to convert
  316. * @param length Number of bytes to convert
  317. * @param btc A ByteToCharConverter
  318. * @exception IndexOutOfBoundsException if the <code>offset</code>
  319. * and <code>count</code> arguments index characters outside
  320. * the bounds of the <code>value</code> array.
  321. */
  322. private String(byte bytes[], int offset, int length,
  323. ByteToCharConverter btc)
  324. {
  325. if (length < 0)
  326. throw new StringIndexOutOfBoundsException("length must be >= 0");
  327. if (offset < 0)
  328. throw new StringIndexOutOfBoundsException("offset must be >= 0");
  329. if (offset > bytes.length-length)
  330. throw new StringIndexOutOfBoundsException(offset + count);
  331. int estCount = btc.getMaxCharsPerByte() * length;
  332. value = new char[estCount];
  333. try {
  334. count = btc.convert(bytes, offset, offset+length,
  335. value, 0, estCount);
  336. count += btc.flush(value, btc.nextCharIndex(), estCount);
  337. } catch (CharConversionException x) {
  338. count = btc.nextCharIndex();
  339. }
  340. if (count < estCount) {
  341. // A multi-byte format was used: Trim the char array.
  342. char[] trimValue = new char[count];
  343. System.arraycopy(value, 0, trimValue, 0, count);
  344. value = trimValue;
  345. }
  346. }
  347. /**
  348. * Construct a new <code>String</code> by converting the specified
  349. * subarray of bytes using the specified character encoding. The length of
  350. * the new <code>String</code> is a function of the encoding, and hence may
  351. * not be equal to the length of the subarray.
  352. *
  353. * @param bytes The bytes to be converted into characters
  354. * @param offset Index of the first byte to convert
  355. * @param length Number of bytes to convert
  356. * @param enc The name of a character encoding
  357. *
  358. * @exception UnsupportedEncodingException
  359. * If the named encoding is not supported
  360. * IndexOutOfBoundsException if the <code>offset</code>
  361. * and <code>count</code> arguments index characters outside
  362. * the bounds of the <code>value</code> array.
  363. * @since JDK1.1
  364. */
  365. public String(byte bytes[], int offset, int length, String enc)
  366. throws UnsupportedEncodingException
  367. {
  368. this(bytes, offset, length, getBTCConverter(enc));
  369. }
  370. /**
  371. * Construct a new <code>String</code> by converting the specified array
  372. * of bytes using the specified character encoding. The length of the new
  373. * <code>String</code> is a function of the encoding, and hence may not be
  374. * equal to the length of the byte array.
  375. *
  376. * @param bytes The bytes to be converted into characters
  377. * @param enc A character-encoding name
  378. *
  379. * @exception UnsupportedEncodingException
  380. * If the named encoding is not supported
  381. * @since JDK1.1
  382. */
  383. public String(byte bytes[], String enc)
  384. throws UnsupportedEncodingException
  385. {
  386. this(bytes, 0, bytes.length, enc);
  387. }
  388. /**
  389. * Construct a new <code>String</code> by converting the specified
  390. * subarray of bytes using the platform's default character encoding. The
  391. * length of the new <code>String</code> is a function of the encoding, and
  392. * hence may not be equal to the length of the subarray.
  393. *
  394. * @param bytes The bytes to be converted into characters
  395. * @param offset Index of the first byte to convert
  396. * @param length Number of bytes to convert
  397. * @since JDK1.1
  398. */
  399. public String(byte bytes[], int offset, int length) {
  400. this(bytes, offset, length, ByteToCharConverter.getDefault());
  401. }
  402. /**
  403. * Construct a new <code>String</code> by converting the specified array
  404. * of bytes using the platform's default character encoding. The length of
  405. * the new <code>String</code> is a function of the encoding, and hence may
  406. * not be equal to the length of the byte array.
  407. *
  408. * @param bytes The bytes to be converted into characters
  409. * @since JDK1.1
  410. */
  411. public String(byte bytes[]) {
  412. this(bytes, 0, bytes.length, ByteToCharConverter.getDefault());
  413. }
  414. /**
  415. * Allocates a new string that contains the sequence of characters
  416. * currently contained in the string buffer argument. The contents of
  417. * the string buffer are copied; subsequent modification of the string
  418. * buffer does not affect the newly created string.
  419. *
  420. * @param buffer a <code>StringBuffer</code>.
  421. * @throws NullPointerException If <code>buffer</code> is
  422. * <code>null</code>.
  423. */
  424. public String (StringBuffer buffer) {
  425. synchronized(buffer) {
  426. buffer.setShared();
  427. this.value = buffer.getValue();
  428. this.offset = 0;
  429. this.count = buffer.length();
  430. }
  431. }
  432. // Private constructor which shares value array for speed.
  433. private String(int offset, int count, char value[]) {
  434. this.value = value;
  435. this.offset = offset;
  436. this.count = count;
  437. }
  438. /**
  439. * Returns the length of this string.
  440. * The length is equal to the number of 16-bit
  441. * Unicode characters in the string.
  442. *
  443. * @return the length of the sequence of characters represented by this
  444. * object.
  445. */
  446. public int length() {
  447. return count;
  448. }
  449. /**
  450. * Returns the character at the specified index. An index ranges
  451. * from <code>0</code> to <code>length() - 1</code>. The first character
  452. * of the sequence is at index <code>0</code>, the next at index
  453. * <code>1</code>, and so on, as for array indexing.
  454. *
  455. * @param index the index of the character.
  456. * @return the character at the specified index of this string.
  457. * The first character is at index <code>0</code>.
  458. * @exception IndexOutOfBoundsException if the <code>index</code>
  459. * argument is negative or not less than the length of this
  460. * string.
  461. */
  462. public char charAt(int index) {
  463. if ((index < 0) || (index >= count)) {
  464. throw new StringIndexOutOfBoundsException(index);
  465. }
  466. return value[index + offset];
  467. }
  468. /**
  469. * Copies characters from this string into the destination character
  470. * array.
  471. * <p>
  472. * The first character to be copied is at index <code>srcBegin</code>
  473. * the last character to be copied is at index <code>srcEnd-1</code>
  474. * (thus the total number of characters to be copied is
  475. * <code>srcEnd-srcBegin</code>). The characters are copied into the
  476. * subarray of <code>dst</code> starting at index <code>dstBegin</code>
  477. * and ending at index:
  478. * <p><blockquote><pre>
  479. * dstbegin + (srcEnd-srcBegin) - 1
  480. * </pre></blockquote>
  481. *
  482. * @param srcBegin index of the first character in the string
  483. * to copy.
  484. * @param srcEnd index after the last character in the string
  485. * to copy.
  486. * @param dst the destination array.
  487. * @param dstBegin the start offset in the destination array.
  488. * @exception IndexOutOfBoundsException If any of the following
  489. * is true:
  490. * <ul><li><code>srcBegin</code> is negative.
  491. * <li><code>srcBegin</code> is greater than <code>srcEnd</code>
  492. * <li><code>srcEnd</code> is greater than the length of this
  493. * string
  494. * <li><code>dstBegin</code> is negative
  495. * <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than
  496. * <code>dst.length</code></ul>
  497. * @exception NullPointerException if <code>dst</code> is <code>null</code>
  498. */
  499. public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
  500. if (srcBegin < 0) {
  501. throw new StringIndexOutOfBoundsException(srcBegin);
  502. }
  503. if (srcEnd > count) {
  504. throw new StringIndexOutOfBoundsException(srcEnd);
  505. }
  506. if (srcBegin > srcEnd) {
  507. throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
  508. }
  509. System.arraycopy(value, offset + srcBegin, dst, dstBegin,
  510. srcEnd - srcBegin);
  511. }
  512. /**
  513. * Copies characters from this string into the destination byte
  514. * array. Each byte receives the 8 low-order bits of the
  515. * corresponding character. The eight high-order bits of each character
  516. * are not copied and do not participate in the transfer in any way.
  517. * <p>
  518. * The first character to be copied is at index <code>srcBegin</code>
  519. * the last character to be copied is at index <code>srcEnd-1</code>.
  520. * The total number of characters to be copied is
  521. * <code>srcEnd-srcBegin</code>. The characters, converted to bytes,
  522. * are copied into the subarray of <code>dst</code> starting at index
  523. * <code>dstBegin</code> and ending at index:
  524. * <p><blockquote><pre>
  525. * dstbegin + (srcEnd-srcBegin) - 1
  526. * </pre></blockquote>
  527. *
  528. * @deprecated This method does not properly convert characters into bytes.
  529. * As of JDK 1.1, the preferred way to do this is via the
  530. * <code>getBytes(String enc)</code> method, which takes a
  531. * character-encoding name, or the <code>getBytes()</code> method, which
  532. * uses the platform's default encoding.
  533. *
  534. * @param srcBegin index of the first character in the string
  535. * to copy.
  536. * @param srcEnd index after the last character in the string
  537. * to copy.
  538. * @param dst the destination array.
  539. * @param dstBegin the start offset in the destination array.
  540. * @exception IndexOutOfBoundsException if any of the following
  541. * is true:
  542. * <ul<li><code>srcBegin</code> is negative
  543. * <li><code>srcBegin</code> is greater than <code>srcEnd</code>
  544. * <li><code>srcEnd</code> is greater than the length of this
  545. * String
  546. * <li><code>dstBegin</code> is negative
  547. * <li><code>dstBegin+(srcEnd-srcBegin)</code> is larger than
  548. * <code>dst.length</code>
  549. * @exception NullPointerException if <code>dst</code> is <code>null</code>
  550. */
  551. public void getBytes(int srcBegin, int srcEnd, byte dst[], int dstBegin) {
  552. if (srcBegin < 0) {
  553. throw new StringIndexOutOfBoundsException(srcBegin);
  554. }
  555. if (srcEnd > count) {
  556. throw new StringIndexOutOfBoundsException(srcEnd);
  557. }
  558. if (srcBegin > srcEnd) {
  559. throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
  560. }
  561. int j = dstBegin;
  562. int n = offset + srcEnd;
  563. int i = offset + srcBegin;
  564. char[] val = value; /* avoid getfield opcode */
  565. while (i < n) {
  566. dst[j++] = (byte)val[i++];
  567. }
  568. }
  569. /**
  570. * Apply the specified character-encoding converter to this String,
  571. * storing the resulting bytes into a new byte array.
  572. *
  573. * @param ctb A CharToByteConverter
  574. * @return The resultant byte array
  575. */
  576. private byte[] getBytes(CharToByteConverter ctb) {
  577. ctb.reset();
  578. int estLength = ctb.getMaxBytesPerChar() * count;
  579. byte[] result = new byte[estLength];
  580. int length = 0;
  581. try {
  582. length += ctb.convertAny(value, offset, (offset + count),
  583. result, 0, estLength);
  584. length += ctb.flushAny(result, ctb.nextByteIndex(), estLength);
  585. } catch (CharConversionException e) {
  586. throw new InternalError("Converter malfunction: " +
  587. ctb.getClass().getName());
  588. }
  589. if (length < estLength) {
  590. // A short format was used: Trim the byte array.
  591. byte[] trimResult = new byte[length];
  592. System.arraycopy(result, 0, trimResult, 0, length);
  593. return trimResult;
  594. }
  595. else {
  596. return result;
  597. }
  598. }
  599. /**
  600. * Convert this <code>String</code> into bytes according to the specified
  601. * character encoding, storing the result into a new byte array.
  602. *
  603. * @param enc A character-encoding name
  604. * @return The resultant byte array
  605. *
  606. * @exception UnsupportedEncodingException
  607. * If the named encoding is not supported
  608. * @since JDK1.1
  609. */
  610. public byte[] getBytes(String enc)
  611. throws UnsupportedEncodingException
  612. {
  613. return getBytes(getCTBConverter(enc));
  614. }
  615. /**
  616. * Convert this <code>String</code> into bytes according to the platform's
  617. * default character encoding, storing the result into a new byte array.
  618. *
  619. * @return the resultant byte array.
  620. * @since JDK1.1
  621. */
  622. public byte[] getBytes() {
  623. return getBytes(CharToByteConverter.getDefault());
  624. }
  625. /**
  626. * Compares this string to the specified object.
  627. * The result is <code>true</code> if and only if the argument is not
  628. * <code>null</code> and is a <code>String</code> object that represents
  629. * the same sequence of characters as this object.
  630. *
  631. * @param anObject the object to compare this <code>String</code>
  632. * against.
  633. * @return <code>true</code> if the <code>String </code>are equal;
  634. * <code>false</code> otherwise.
  635. * @see java.lang.String#compareTo(java.lang.String)
  636. * @see java.lang.String#equalsIgnoreCase(java.lang.String)
  637. */
  638. public boolean equals(Object anObject) {
  639. if (this == anObject) {
  640. return true;
  641. }
  642. if ((anObject != null) && (anObject instanceof String)) {
  643. String anotherString = (String)anObject;
  644. int n = count;
  645. if (n == anotherString.count) {
  646. char v1[] = value;
  647. char v2[] = anotherString.value;
  648. int i = offset;
  649. int j = anotherString.offset;
  650. while (n-- != 0) {
  651. if (v1[i++] != v2[j++]) {
  652. return false;
  653. }
  654. }
  655. return true;
  656. }
  657. }
  658. return false;
  659. }
  660. /**
  661. * Compares this <code>String</code> to another <code>String</code>,
  662. * ignoring case considerations. Two strings are considered equal
  663. * ignoring case if they are of the same length, and corresponding
  664. * characters in the two strings are equal ignoring case.
  665. * <p>
  666. * Two characters <code>c1</code> and <code>c2</code> are considered
  667. * the same, ignoring case if at least one of the following is true:
  668. * <ul><li>The two characters are the same (as compared by the
  669. * <code>==</code> operator).
  670. * <li>Applying the method {@link java.lang.Character#toUppercase(char)}
  671. * to each character produces the same result.
  672. * <li>Applying the method {@link java.lang.Character#toLowercase(char)
  673. * to each character produces the same result.</ul>
  674. *
  675. * @param anotherString the <code>String</code> to compare this
  676. * <code>String</code> against.
  677. * @return <code>true</code> if the argument is not <code>null</code>
  678. * and the <code>String</code>s are equal,
  679. * ignoring case; <code>false</code> otherwise.
  680. * @see #equals(Object)
  681. * @see java.lang.Character#toLowerCase(char)
  682. * @see java.lang.Character#toUpperCase(char)
  683. */
  684. public boolean equalsIgnoreCase(String anotherString) {
  685. return (anotherString != null) && (anotherString.count == count) &&
  686. regionMatches(true, 0, anotherString, 0, count);
  687. }
  688. /**
  689. * Compares two strings lexicographically.
  690. * The comparison is based on the Unicode value of each character in
  691. * the strings. The character sequence represented by this
  692. * <code>String</code> object is compared lexicographically to the
  693. * character sequence represented by the argument string. The result is
  694. * a negative integer if this <code>String</code> object
  695. * lexicographically precedes the argument string. The result is a
  696. * positive integer if this <code>String</code> object lexicographically
  697. * follows the argument string. The result is zero if the strings
  698. * are equal; <code>compareTo</code> returns <code>0</code> exactly when
  699. * the {@link #equals(Object)} method would return <code>true</code>.
  700. * <p>
  701. * This is the definition of lexicographic ordering. If two strings are
  702. * different, then either they have different characters at some index
  703. * that is a valid index for both strings, or their lengths are different,
  704. * or both. If they have different characters at one or more index
  705. * positions, let <i>k</i> be the smallest such index; then the string
  706. * whose character at position <i>k</i> has the smaller value, as
  707. * determined by using the < operator, lexicographically precedes the
  708. * other string. In this case, <code>compareTo</code> returns the
  709. * difference of the two character values at position <code>k</code> in
  710. * the two string -- that is, the value:
  711. * <blockquote><pre>
  712. * this.charAt(k)-anotherString.charAt(k)
  713. * </pre></blockquote>
  714. * If there is no index position at which they differ, then the shorter
  715. * string lexicographically precedes the longer string. In this case,
  716. * <code>compareTo</code> returns the difference of the lengths of the
  717. * strings -- that is, the value:
  718. * <blockquote><pre>
  719. * this.length()-anotherString.length()
  720. * </pre></blockquote>
  721. *
  722. * @param anotherString the <code>String</code> to be compared.
  723. * @return the value <code>0</code> if the argument string is equal to
  724. * this string; a value less than <code>0</code> if this string
  725. * is lexicographically less than the string argument; and a
  726. * value greater than <code>0</code> if this string is
  727. * lexicographically greater than the string argument.
  728. * @exception java.lang.NullPointerException if <code>anotherString</code>
  729. * is <code>null</code>.
  730. */
  731. public int compareTo(String anotherString) {
  732. int len1 = count;
  733. int len2 = anotherString.count;
  734. int n = Math.min(len1, len2);
  735. char v1[] = value;
  736. char v2[] = anotherString.value;
  737. int i = offset;
  738. int j = anotherString.offset;
  739. while (n-- != 0) {
  740. char c1 = v1[i++];
  741. char c2 = v2[j++];
  742. if (c1 != c2) {
  743. return c1 - c2;
  744. }
  745. }
  746. return len1 - len2;
  747. }
  748. /**
  749. * Compares this String to another Object. If the Object is a String,
  750. * this function behaves like <code>compareTo(String)</code>. Otherwise,
  751. * it throws a <code>ClassCastException</code> (as Strings are comparable
  752. * only to other Strings).
  753. *
  754. * @param o the <code>Object</code> to be compared.
  755. * @return the value <code>0</code> if the argument is a string
  756. * lexicographically equal to this string; a value less than
  757. * <code>0</code> if the argument is a string lexicographically
  758. * greater than this string; and a value greater than
  759. * <code>0</code> if the argument is a string lexicographically
  760. * less than this string.
  761. * @exception <code>ClassCastException</code> if the argument is not a
  762. * <code>String</code>.
  763. * @see java.lang.Comparable
  764. * @since JDK1.2
  765. */
  766. public int compareTo(Object o) {
  767. return compareTo((String)o);
  768. }
  769. /**
  770. * Returns a Comparator that orders <code>String</code> objects as by
  771. * <code>compareToIgnoreCase</code>.
  772. * <p>
  773. * Note that this Comparator does <em>not</em> take locale into account,
  774. * and will result in an unsatisfactory ordering for certain locales.
  775. * The java.text package provides <em>Collators</em> to allow
  776. * locale-sensitive ordering.
  777. *
  778. * @return Comparator for case insensitive comparison of strings
  779. * @see java.text.Collator#compare(String, String)
  780. * @since JDK1.2
  781. */
  782. public static final Comparator CASE_INSENSITIVE_ORDER
  783. = new CaseInsensitiveComparator();
  784. private static class CaseInsensitiveComparator
  785. implements Comparator, java.io.Serializable {
  786. public int compare(Object o1, Object o2) {
  787. String s1 = (String) o1;
  788. String s2 = (String) o2;
  789. int n1=s1.length(), n2=s2.length();
  790. for (int i1=0, i2=0; i1<n1 && i2<n2; i1++, i2++) {
  791. char c1 = s1.charAt(i1);
  792. char c2 = s2.charAt(i2);
  793. if (c1 != c2) {
  794. c1 = Character.toUpperCase(c1);
  795. c2 = Character.toUpperCase(c2);
  796. if (c1 != c2) {
  797. c1 = Character.toLowerCase(c1);
  798. c2 = Character.toLowerCase(c2);
  799. if (c1 != c2)
  800. return c1 - c2;
  801. }
  802. }
  803. }
  804. return n1 - n2;
  805. }
  806. }
  807. /**
  808. * Compares two strings lexicographically, ignoring case considerations.
  809. * This method returns an integer whose sign is that of
  810. * <code>this.toUpperCase().toLowerCase().compareTo(
  811. * str.toUpperCase().toLowerCase())</code>.
  812. * <p>
  813. * Note that this method does <em>not</em> take locale into account,
  814. * and will result in an unsatisfactory ordering for certain locales.
  815. * The java.text package provides <em>collators</em> to allow
  816. * locale-sensitive ordering.
  817. *
  818. * @param str the <code>String</code> to be compared.
  819. * @return a negative integer, zero, or a positive integer as the
  820. * the specified String is greater than, equal to, or less
  821. * than this String, ignoring case considerations.
  822. * @see java.text.Collator#compare(String, String)
  823. * @since JDK1.2
  824. */
  825. public int compareToIgnoreCase(String str) {
  826. return CASE_INSENSITIVE_ORDER.compare(this, str);
  827. }
  828. /**
  829. * Tests if two string regions are equal.
  830. * <p>
  831. * A substring of this <tt>String</tt> object is compared to a substring
  832. * of the argument other. The result is true if these substrings
  833. * represent identical character sequences. The substring of this
  834. * <tt>String</tt> object to be compared begins at index <tt>toffset</tt>
  835. * and has length <tt>len</tt>. The substring of other to be compared
  836. * begins at index <tt>ooffset</tt> and has length <tt>len</tt>. The
  837. * result is <tt>false</tt> if and only if at least one of the following
  838. * is true:
  839. * <ul><li><tt>toffset</tt> is negative.
  840. * <li><tt>ooffset</tt> is negative.
  841. * <li><tt>toffset+len</tt> is greater than the length of this
  842. * <tt>String</tt> object.
  843. * <li><tt>ooffset+len</tt> is greater than the length of the other
  844. * argument.
  845. * <li>There is some nonnegative integer <i>k</i> less than <tt>len</tt>
  846. * such that:
  847. * <tt>this.charAt(toffset+<i>k</i>) != other.charAt(ooffset+<i>k</i>)</tt>
  848. * </u>
  849. *
  850. * @param toffset the starting offset of the subregion in this string.
  851. * @param other the string argument.
  852. * @param ooffset the starting offset of the subregion in the string
  853. * argument.
  854. * @param len the number of characters to compare.
  855. * @return <code>true</code> if the specified subregion of this string
  856. * exactly matches the specified subregion of the string argument;
  857. * <code>false</code> otherwise.
  858. * @exception java.lang.NullPointerException if <tt>other</tt> is
  859. * <tt>null</tt>.
  860. */
  861. public boolean regionMatches(int toffset, String other, int ooffset,
  862. int len) {
  863. char ta[] = value;
  864. int to = offset + toffset;
  865. int tlim = offset + count;
  866. char pa[] = other.value;
  867. int po = other.offset + ooffset;
  868. // Note: toffset, ooffset, or len might be near -1>>>1.
  869. if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len)
  870. || (ooffset > (long)other.count - len)) {
  871. return false;
  872. }
  873. while (len-- > 0) {
  874. if (ta[to++] != pa[po++]) {
  875. return false;
  876. }
  877. }
  878. return true;
  879. }
  880. /**
  881. * Tests if two string regions are equal.
  882. * <p>
  883. * A substring of this <tt>String</tt> object is compared to a substring
  884. * of the argument <tt>other</tt>. The result is <tt>true</tt> if these
  885. * substrings represent character sequences that are the same, ignoring
  886. * case if and only if <tt>ignoreCase</tt> is true. The substring of
  887. * this <tt>String</tt> object to be compared begins at index
  888. * <tt>toffset</tt> and has length <tt>len</tt>. The substring of
  889. * <tt>other</tt> to be compared begins at index <tt>ooffset</tt> and
  890. * has length <tt>len</tt>. The result is <tt>false</tt> if and only if
  891. * at least one of the following is true:
  892. * <ul><li><tt>toffset</tt> is negative.
  893. * <li><tt>ooffset</tt> is negative.
  894. * <li><tt>toffset+len</tt> is greater than the length of this
  895. * <tt>String</tt> object.
  896. * <li><tt>ooffset+len</tt> is greater than the length of the other
  897. * argument.
  898. * <li>There is some nonnegative integer <i>k</i> less than <tt>len</tt>
  899. * such that:
  900. * <blockquote><pre>
  901. * this.charAt(toffset+k) != other.charAt(ooffset+k)
  902. * </pre></blockquote>
  903. * <li><tt>ignoreCase</tt> is <tt>true</tt> and there is some nonnegative
  904. * integer <i>k</i> less than <tt>len</tt> such that:
  905. * <blockquote><pre>
  906. * Character.toLowerCase(this.charAt(toffset+k)) !=
  907. Character.toLowerCase(other.charAt(ooffset+k))
  908. * </pre></blockquote>
  909. * and:
  910. * <blockquote><pre>
  911. * Character.toUpperCase(this.charAt(toffset+k)) !=
  912. * Character.toUpperCase(other.charAt(ooffset+k))
  913. * </pre></blockquote>
  914. * </ul>
  915. *
  916. * @param ignoreCase if <code>true</code>, ignore case when comparing
  917. * characters.
  918. * @param toffset the starting offset of the subregion in this
  919. * string.
  920. * @param other the string argument.
  921. * @param ooffset the starting offset of the subregion in the string
  922. * argument.
  923. * @param len the number of characters to compare.
  924. * @return <code>true</code> if the specified subregion of this string
  925. * matches the specified subregion of the string argument;
  926. * <code>false</code> otherwise. Whether the matching is exact
  927. * or case insensitive depends on the <code>ignoreCase</code>
  928. * argument.
  929. */
  930. public boolean regionMatches(boolean ignoreCase,
  931. int toffset,
  932. String other, int ooffset, int len) {
  933. char ta[] = value;
  934. int to = offset + toffset;
  935. int tlim = offset + count;
  936. char pa[] = other.value;
  937. int po = other.offset + ooffset;
  938. // Note: toffset, ooffset, or len might be near -1>>>1.
  939. if ((ooffset < 0) || (toffset < 0) || (toffset > (long)count - len) ||
  940. (ooffset > (long)other.count - len)) {
  941. return false;
  942. }
  943. while (len-- > 0) {
  944. char c1 = ta[to++];
  945. char c2 = pa[po++];
  946. if (c1 == c2)
  947. continue;
  948. if (ignoreCase) {
  949. // If characters don't match but case may be ignored,
  950. // try converting both characters to uppercase.
  951. // If the results match, then the comparison scan should
  952. // continue.
  953. char u1 = Character.toUpperCase(c1);
  954. char u2 = Character.toUpperCase(c2);
  955. if (u1 == u2)
  956. continue;
  957. // Unfortunately, conversion to uppercase does not work properly
  958. // for the Georgian alphabet, which has strange rules about case
  959. // conversion. So we need to make one last check before
  960. // exiting.
  961. if (Character.toLowerCase(u1) == Character.toLowerCase(u2))
  962. continue;
  963. }
  964. return false;
  965. }
  966. return true;
  967. }
  968. /**
  969. * Tests if this string starts with the specified prefix beginning
  970. * a specified index.
  971. *
  972. * @param prefix the prefix.
  973. * @param toffset where to begin looking in the string.
  974. * @return <code>true</code> if the character sequence represented by the
  975. * argument is a prefix of the substring of this object starting
  976. * at index <code>toffset</code> <code>false</code> otherwise.
  977. * The result is <code>false</code> if <code>toffset</code> is
  978. * negative or greater than the length of this
  979. * <code>String</code> object; otherwise the result is the same
  980. * as the result of the expression
  981. * <pre>
  982. * this.subString(toffset).startsWith(prefix)
  983. * </pre>
  984. * @exception java.lang.NullPointerException if <code>prefix</code> is
  985. * <code>null</code>.
  986. */
  987. public boolean startsWith(String prefix, int toffset) {
  988. char ta[] = value;
  989. int to = offset + toffset;
  990. int tlim = offset + count;
  991. char pa[] = prefix.value;
  992. int po = prefix.offset;
  993. int pc = prefix.count;
  994. // Note: toffset might be near -1>>>1.
  995. if ((toffset < 0) || (toffset > count - pc)) {
  996. return false;
  997. }
  998. while (--pc >= 0) {
  999. if (ta[to++] != pa[po++]) {
  1000. return false;
  1001. }
  1002. }
  1003. return true;
  1004. }
  1005. /**
  1006. * Tests if this string starts with the specified prefix.
  1007. *
  1008. * @param prefix the prefix.
  1009. * @return <code>true</code> if the character sequence represented by the
  1010. * argument is a prefix of the character sequence represented by
  1011. * this string; <code>false</code> otherwise.
  1012. * Note also that <code>true</code> will be returned if the
  1013. * argument is an empty string or is equal to this
  1014. * <code>String</code> object as determined by the
  1015. * {@link #equals(Object)} method.
  1016. * @exception java.lang.NullPointerException if <code>prefix</code> is
  1017. * <code>null</code>.
  1018. * @since JDK1. 0
  1019. */
  1020. public boolean startsWith(String prefix) {
  1021. return startsWith(prefix, 0);
  1022. }
  1023. /**
  1024. * Tests if this string ends with the specified suffix.
  1025. *
  1026. * @param suffix the suffix.
  1027. * @return <code>true</code> if the character sequence represented by the
  1028. * argument is a suffix of the character sequence represented by
  1029. * this object; <code>false</code> otherwise. Note that the
  1030. * result will be <code>true</code> if the argument is the
  1031. * empty string or is equal to this <code>String</code> object
  1032. * as determined by the {@link #equals(Object)} method.
  1033. * @exception java.lang.NullPointerException if <code>suffix</code> is
  1034. * <code>null</code>.
  1035. */
  1036. public boolean endsWith(String suffix) {
  1037. return startsWith(suffix, count - suffix.count);
  1038. }
  1039. /**
  1040. * Returns a hashcode for this string. The hashcode for a
  1041. * <code>String</code> object is computed as
  1042. * <blockquote><pre>
  1043. * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
  1044. * </pre></blockquote>
  1045. * using <code>int</code> arithmetic, where <code>s[i]</code> is the
  1046. * <i>i</i>th character of the string, <code>n</code> is the length of
  1047. * the string, and <code>^</code> indicates exponentiation.
  1048. * (The hash value of the empty string is zero.)
  1049. *
  1050. * @return a hash code value for this object.
  1051. */
  1052. public int hashCode() {
  1053. int h = 0;
  1054. int off = offset;
  1055. char val[] = value;
  1056. int len = count;
  1057. for (int i = 0; i < len; i++)
  1058. h = 31*h + val[off++];
  1059. return h;
  1060. }
  1061. /**
  1062. * Returns the index within this string of the first occurrence of the
  1063. * specified character. If a character with value <code>ch</code> occurs
  1064. * in the character sequence represented by this <code>String</code>
  1065. * object, then the index of the first such occurrence is returned --
  1066. * that is, the smallest value <i>k</i> such that:
  1067. * <blockquote><pre>
  1068. * this.charAt(<i>k</i>) == ch
  1069. * </pre></blockquote>
  1070. * is <code>true</code>. If no such character occurs in this string,
  1071. * then <code>-1</code> is returned.
  1072. *
  1073. * @param ch a character.
  1074. * @return the index of the first occurrence of the character in the
  1075. * character sequence represented by this object, or
  1076. * <code>-1</code> if the character does not occur.
  1077. */
  1078. public int indexOf(int ch) {
  1079. return indexOf(ch, 0);
  1080. }
  1081. /**
  1082. * Returns the index within this string of the first occurrence of the
  1083. * specified character, starting the search at the specified index.
  1084. * <p>
  1085. * If a character with value <code>ch</code> occurs in the character
  1086. * sequence represented by this <code>String</code> object at an index
  1087. * no smaller than <code>fromIndex</code>, then the index of the first
  1088. * such occurrence is returned--that is, the smallest value <i>k</i>
  1089. * such that:
  1090. * <blockquote><pre>
  1091. * (this.charAt(<i>k</i>) == ch) && (<i>k</i> >= fromIndex)
  1092. * </pre></blockquote>
  1093. * is true. If no such character occurs in this string at or after
  1094. * position <code>fromIndex</code>, then <code>-1</code> is returned.
  1095. * <p>
  1096. * There is no restriction on the value of <code>fromIndex</code>. If it
  1097. * is negative, it has the same effect as if it were zero: this entire
  1098. * string may be searched. If it is greater than the length of this
  1099. * string, it has the same effect as if it were equal to the length of
  1100. * this string: <code>-1</code> is returned.
  1101. *
  1102. * @param ch a character.
  1103. * @param fromIndex the index to start the search from.
  1104. * @return the index of the first occurrence of the character in the
  1105. * character sequence represented by this object that is greater
  1106. * than or equal to <code>fromIndex</code>, or <code>-1</code>
  1107. * if the character does not occur.
  1108. */
  1109. public int indexOf(int ch, int fromIndex) {
  1110. int max = offset + count;
  1111. char v[] = value;
  1112. if (fromIndex < 0) {
  1113. fromIndex = 0;
  1114. } else if (fromIndex >= count) {
  1115. // Note: fromIndex might be near -1>>>1.
  1116. return -1;
  1117. }
  1118. for (int i = offset + fromIndex ; i < max ; i++) {
  1119. if (v[i] == ch) {
  1120. return i - offset;
  1121. }
  1122. }
  1123. return -1;
  1124. }
  1125. /**
  1126. * Returns the index within this string of the last occurrence of the
  1127. * specified character. That is, the index returned is the largest
  1128. * value <i>k</i> such that:
  1129. * <blockquote><pre>
  1130. * this.charAt(<i>k</i>) == ch
  1131. * </pre></blockquote>
  1132. * is true.
  1133. * The String is searched backwards starting at the last character.
  1134. *
  1135. * @param ch a character.
  1136. * @return the index of the last occurrence of the character in the
  1137. * character sequence represented by this object, or
  1138. * <code>-1</code> if the character does not occur.
  1139. */
  1140. public int lastIndexOf(int ch) {
  1141. return lastIndexOf(ch, count - 1);
  1142. }
  1143. /**
  1144. * Returns the index within this string of the last occurrence of the
  1145. * specified character, searching backward starting at the specified
  1146. * index. That is, the index returned is the largest value <i>k</i>
  1147. * such that:
  1148. * <blockquote><pre>
  1149. * this.charAt(k) == ch) && (k <= fromIndex)
  1150. * </pre></blockquote>
  1151. * is true.
  1152. *
  1153. * @param ch a character.
  1154. * @param fromIndex the index to start the search from. There is no
  1155. * restriction on the value of <code>fromIndex</code>. If it is
  1156. * greater than or equal to the length of this string, it has
  1157. * the same effect as if it were equal to one less than the
  1158. * length of this string: this entire string may be searched.
  1159. * If it is negative, it has the same effect as if it were -1:
  1160. * -1 is returned.
  1161. * @return the index of the last occurrence of the character in the
  1162. * character sequence represented by this object that is less
  1163. * than or equal to <code>fromIndex</code>, or <code>-1</code>
  1164. * if the character does not occur before that point.
  1165. */
  1166. public int lastIndexOf(int ch, int fromIndex) {
  1167. int min = offset;
  1168. char v[] = value;
  1169. for (int i = offset + ((fromIndex >= count) ? count - 1 : fromIndex) ; i >= min ; i--) {
  1170. if (v[i] == ch) {
  1171. return i - offset;
  1172. }
  1173. }
  1174. return -1;
  1175. }
  1176. /**
  1177. * Returns the index within this string of the first occurrence of the
  1178. * specified substring. The integer returned is the smallest value
  1179. * <i>k</i> such that:
  1180. * <blockquote><pre>
  1181. * this.startsWith(str, <i>k</i>)
  1182. * </pre></blockquote>
  1183. * is <code>true</code>.
  1184. *
  1185. * @param str any string.
  1186. * @return if the string argument occurs as a substring within this
  1187. * object, then the index of the first character of the first
  1188. * such substring is returned; if it does not occur as a
  1189. * substring, <code>-1</code> is returned.
  1190. * @exception java.lang.NullPointerException if <code>str</code> is
  1191. * <code>null</code>.
  1192. */
  1193. public int indexOf(String str) {
  1194. return indexOf(str, 0);
  1195. }
  1196. /**
  1197. * Returns the index within this string of the first occurrence of the
  1198. * specified substring, starting at the specified index. The integer
  1199. * returned is the smallest value <i>k</i> such that:
  1200. * <blockquote><pre>
  1201. * this.startsWith(str, <i>k</i>) && (<i>k</i> >= fromIndex)
  1202. * </pre></blockquote>
  1203. * is <code>true</code>.
  1204. * <p>
  1205. * There is no restriction on the value of <code>fromIndex</code>. If
  1206. * it is negative, it has the same effect as if it were zero: this entire
  1207. * string may be searched. If it is greater than the length of this
  1208. * string, it has the same effect as if it were equal to the length of
  1209. * this string: <code>-1</code> is returned.
  1210. *
  1211. * @param str the substring to search for.
  1212. * @param fromIndex the index to start the search from.
  1213. * @return If the string argument occurs as a substring within this
  1214. * object at a starting index no smaller than
  1215. * <code>fromIndex</code>, then the index of the first character
  1216. * of the first such substring is returned. If it does not occur
  1217. * as a substring starting at <code>fromIndex</code> or beyond,
  1218. * <code>-1</code> is returned.
  1219. * @exception java.lang.NullPointerException if <code>str</code> is
  1220. * <code>null</code>
  1221. */
  1222. public int indexOf(String str, int fromIndex) {
  1223. char v1[] = value;
  1224. char v2[] = str.value;
  1225. int max = offset + (count - str.count);
  1226. if (fromIndex >= count) {
  1227. if (count == 0 && fromIndex == 0 && str.count == 0) {
  1228. /* There is an empty string at index 0 in an empty string. */
  1229. return 0;
  1230. }
  1231. /* Note: fromIndex might be near -1>>>1 */
  1232. return -1;
  1233. }
  1234. if (fromIndex < 0) {
  1235. fromIndex = 0;
  1236. }
  1237. if (str.count == 0) {
  1238. return fromIndex;
  1239. }
  1240. int strOffset = str.offset;
  1241. char first = v2[strOffset];
  1242. int i = offset + fromIndex;
  1243. startSearchForFirstChar:
  1244. while (true) {
  1245. /* Look for first character. */
  1246. while (i <= max && v1[i] != first) {
  1247. i++;
  1248. }
  1249. if (i > max) {
  1250. return -1;
  1251. }
  1252. /* Found first character, now look at the rest of v2 */
  1253. int j = i + 1;
  1254. int end = j + str.count - 1;
  1255. int k = strOffset + 1;
  1256. while (j < end) {
  1257. if (v1[j++] != v2[k++]) {
  1258. i++;
  1259. /* Look for str's first char again. */
  1260. continue startSearchForFirstChar;
  1261. }
  1262. }
  1263. return i - offset; /* Found whole string. */
  1264. }
  1265. }
  1266. /**
  1267. * Returns the index within this string of the rightmost occurrence
  1268. * of the specified substring. The rightmost empty string "" is
  1269. * considered to occur at the index value <code>this.length()</code>.
  1270. * The returned index is the largest value <i>k</i> such that
  1271. * <blockquote><pre>
  1272. * this.startsWith(str, k)
  1273. * </pre></blockquote>
  1274. * is true.
  1275. *
  1276. * @param str the substring to search for.
  1277. * @return if the string argument occurs one or more times as a substring
  1278. * within this object, then the index of the first character of
  1279. * the last such substring is returned. If it does not occur as
  1280. * a substring, <code>-1</code> is returned.
  1281. * @exception java.lang.NullPointerException if <code>str</code> is
  1282. * <code>null</code>.
  1283. */
  1284. public int lastIndexOf(String str) {
  1285. return lastIndexOf(str, count);
  1286. }
  1287. /**
  1288. * Returns the index within this string of the last occurrence of
  1289. * the specified substring.
  1290. * The returned index indicates the start of the substring, and it
  1291. * must be equal to or less than <code>fromIndex</code>. That is,
  1292. * the index returned is the largest value <i>k</i> such that:
  1293. * <blockquote><pre>
  1294. * this.startsWith(str, k) && (k <= fromIndex)
  1295. * </pre></blockquote>
  1296. *
  1297. * @param str the substring to search for.
  1298. * @param fromIndex the index to start the search from. There is no
  1299. * restriction on the value of fromIndex. If it is greater than
  1300. * the length of this string, it has the same effect as if it
  1301. * were equal to the length of this string: this entire string
  1302. * may be searched. If it is negative, it has the same effect
  1303. * as if it were -1: -1 is returned.
  1304. * @return If the string argument occurs one or more times as a substring
  1305. * within this object at a starting index no greater than
  1306. * <code>fromIndex</code>, then the index of the first character of
  1307. * the last such substring is returned. If it does not occur as a
  1308. * substring starting at <code>fromIndex</code> or earlier,
  1309. * <code>-1</code> is returned.
  1310. * @exception java.lang.NullPointerException if <code>str</code> is
  1311. * <code>null</code>.
  1312. */
  1313. public int lastIndexOf(String str, int fromIndex) {
  1314. /*
  1315. * Check arguments; return immediately where possible. For
  1316. * consistency, don't check for null str.
  1317. */
  1318. int rightIndex = count - str.count;
  1319. if (fromIndex < 0) {
  1320. return -1;
  1321. }
  1322. if (fromIndex > rightIndex) {
  1323. fromIndex = rightIndex;
  1324. }
  1325. /* Empty string always matches. */
  1326. if (str.count == 0) {
  1327. return fromIndex;
  1328. }
  1329. char v1[] = value;
  1330. char v2[] = str.value;
  1331. int strLastIndex = str.offset + str.count - 1;
  1332. char strLastChar = v2[strLastIndex];
  1333. int min = offset + str.count - 1;
  1334. int i = min + fromIndex;
  1335. startSearchForLastChar:
  1336. while (true) {
  1337. /* Look for the last character */
  1338. while (i >= min && v1[i] != strLastChar) {
  1339. i--;
  1340. }
  1341. if (i < min) {
  1342. return -1;
  1343. }
  1344. /* Found last character, now look at the rest of v2. */
  1345. int j = i - 1;
  1346. int start = j - (str.count - 1);
  1347. int k = strLastIndex - 1;
  1348. while (j > start) {
  1349. if (v1[j--] != v2[k--]) {
  1350. i--;
  1351. /* Look for str's last char again. */
  1352. continue startSearchForLastChar;
  1353. }
  1354. }
  1355. return start - offset + 1; /* Found whole string. */
  1356. }
  1357. }
  1358. /**
  1359. * Returns a new string that is a substring of this string. The
  1360. * substring begins with the character at the specified index and
  1361. * extends to the end of this string. <p>
  1362. * Examples:
  1363. * <blockquote><pre>
  1364. * "unhappy".substring(2) returns "happy"
  1365. * "Harbison".substring(3) returns "bison"
  1366. * "emptiness".substring(9) returns "" (an empty string)
  1367. * </pre></blockquote>
  1368. *
  1369. * @param beginIndex the beginning index, inclusive.
  1370. * @return the specified substring.
  1371. * @exception IndexOutOfBoundsException if
  1372. * <code>beginIndex</code> is negative or larger than the
  1373. * length of this <code>String</code> object.
  1374. */
  1375. public String substring(int beginIndex) {
  1376. return substring(beginIndex, count);
  1377. }
  1378. /**
  1379. * Returns a new string that is a substring of this string. The
  1380. * substring begins at the specified <code>beginIndex</code> and
  1381. * extends to the character at index <code>endIndex - 1</code>.
  1382. * Thus the length of the substring is <code>endIndex-beginIndex</code>.
  1383. * <p>
  1384. * Examples:
  1385. * <blockquote><pre>
  1386. * "hamburger".substring(4, 8) returns "urge"
  1387. * "smiles".substring(1, 5) returns "mile"
  1388. * </pre></blockquote>
  1389. *
  1390. * @param beginIndex the beginning index, inclusive.
  1391. * @param endIndex the ending index, exclusive.
  1392. * @return the specified substring.
  1393. * @exception IndexOutOfBoundsException if the
  1394. *