OLD | NEW |
(Empty) | |
| 1 // © 2017 and later: Unicode, Inc. and others. |
| 2 // License & terms of use: http://www.unicode.org/copyright.html#License |
| 3 package com.ibm.icu.impl.number; |
| 4 |
| 5 public class DoubleSidedStringBuilder implements CharSequence { |
| 6 private char[] chars; |
| 7 private int zero; |
| 8 private int length; |
| 9 |
| 10 public DoubleSidedStringBuilder() { |
| 11 this(40); |
| 12 } |
| 13 |
| 14 public DoubleSidedStringBuilder(int capacity) { |
| 15 chars = new char[capacity]; |
| 16 zero = capacity / 2; |
| 17 length = 0; |
| 18 } |
| 19 |
| 20 @Override |
| 21 public int length() { |
| 22 return length; |
| 23 } |
| 24 |
| 25 @Override |
| 26 public char charAt(int index) { |
| 27 if (index < 0 || index > length) { |
| 28 throw new IndexOutOfBoundsException(); |
| 29 } |
| 30 return chars[zero + index]; |
| 31 } |
| 32 |
| 33 /** Appends the specified codePoint to the end of the string. */ |
| 34 public int appendCodePoint(int codePoint) { |
| 35 return insertCodePoint(length, codePoint); |
| 36 } |
| 37 |
| 38 /** Inserts the specified codePoint at the specified index in the string. */ |
| 39 public int insertCodePoint(int index, int codePoint) { |
| 40 int charCount = Character.charCount(codePoint); |
| 41 if (index == 0 && zero - charCount >= 0) { |
| 42 // Append to start |
| 43 zero -= charCount; |
| 44 Character.toChars(codePoint, chars, zero); |
| 45 length += charCount; |
| 46 } else if (index == length && zero + length + charCount < chars.length) { |
| 47 // Append to end |
| 48 Character.toChars(codePoint, chars, zero + length); |
| 49 length += charCount; |
| 50 } else { |
| 51 // Move chars around and/or allocate more space |
| 52 adjustForInsert(index, charCount); |
| 53 Character.toChars(codePoint, chars, zero + index); |
| 54 } |
| 55 return charCount; |
| 56 } |
| 57 |
| 58 /** Appends the specified CharSequence to the end of the string. */ |
| 59 public int append(CharSequence sequence) { |
| 60 return insert(length, sequence); |
| 61 } |
| 62 |
| 63 /** Inserts the specified CharSequence at the specified index in the string. *
/ |
| 64 public int insert(int index, CharSequence sequence) { |
| 65 if (sequence.length() == 1) { |
| 66 // Fast path: on a single-char string, using insertCodePoint below is 70%
faster than the |
| 67 // CharSequence method: 12.2 ns versus 41.9 ns for five operations on my L
inux x86-64. |
| 68 return insertCodePoint(index, sequence.charAt(0)); |
| 69 } else { |
| 70 return insert(index, sequence, 0, sequence.length()); |
| 71 } |
| 72 } |
| 73 |
| 74 /** |
| 75 * Inserts the specified CharSequence at the specified index in the string, re
ading from the |
| 76 * CharSequence from start (inclusive) to end (exclusive). |
| 77 */ |
| 78 public int insert(int index, CharSequence sequence, int start, int end) { |
| 79 int count = end - start; |
| 80 if (index == 0 && zero - count >= 0) { |
| 81 // Append to start |
| 82 zero -= count; |
| 83 copyCharSequence(sequence, start, chars, zero, count); |
| 84 length += count; |
| 85 } else if (index == length && zero + length + count < chars.length) { |
| 86 // Append to end |
| 87 copyCharSequence(sequence, start, chars, zero + length, count); |
| 88 length += count; |
| 89 } else { |
| 90 // Move chars around and/or allocate more space |
| 91 adjustForInsert(index, count); |
| 92 copyCharSequence(sequence, start, chars, zero + index, count); |
| 93 } |
| 94 return count; |
| 95 } |
| 96 |
| 97 private void copyCharSequence( |
| 98 CharSequence source, int srcIndex, char[] dest, int destIndex, int count)
{ |
| 99 for (int i = 0; i < count; i++) { |
| 100 dest[destIndex + i] = source.charAt(srcIndex + i); |
| 101 } |
| 102 } |
| 103 |
| 104 private void adjustForInsert(int index, int count) { |
| 105 if (length + count > chars.length) { |
| 106 char[] newChars = new char[(length + count) * 2]; |
| 107 int newZero = newChars.length / 2 - (length + count) / 2; |
| 108 System.arraycopy(chars, zero, newChars, newZero, index); |
| 109 System.arraycopy(chars, zero + index, newChars, newZero + index + count, l
ength - index); |
| 110 chars = newChars; |
| 111 zero = newZero; |
| 112 length += count; |
| 113 } else { |
| 114 int newZero = chars.length / 2 - (length + count) / 2; |
| 115 System.arraycopy(chars, zero, chars, newZero, length); |
| 116 System.arraycopy(chars, newZero + index, chars, newZero + index + count, l
ength - index); |
| 117 zero = newZero; |
| 118 length += count; |
| 119 } |
| 120 } |
| 121 |
| 122 @Override |
| 123 public CharSequence subSequence(int start, int end) { |
| 124 if (start < 0 || end > length || end < start) { |
| 125 throw new IndexOutOfBoundsException(); |
| 126 } |
| 127 DoubleSidedStringBuilder other = this.clone(); |
| 128 other.zero = zero + start; |
| 129 other.length = end - start; |
| 130 return other; |
| 131 } |
| 132 |
| 133 @Override |
| 134 public String toString() { |
| 135 return new String(chars, zero, length); |
| 136 } |
| 137 |
| 138 @Override |
| 139 public DoubleSidedStringBuilder clone() { |
| 140 DoubleSidedStringBuilder other = new DoubleSidedStringBuilder(chars.length); |
| 141 other.zero = zero; |
| 142 other.length = length; |
| 143 System.arraycopy(chars, zero, chars, zero, length); |
| 144 return other; |
| 145 } |
| 146 |
| 147 public DoubleSidedStringBuilder clear() { |
| 148 zero = chars.length / 2; |
| 149 length = 0; |
| 150 return this; |
| 151 } |
| 152 } |
OLD | NEW |