1717
1818package com .itsaky .androidide .treesitter .string ;
1919
20+ import static com .itsaky .androidide .treesitter .string .Assertions .checkIndex ;
21+ import static com .itsaky .androidide .treesitter .string .Assertions .checkStringRange ;
22+
2023import java .util .Objects ;
2124
2225/**
@@ -36,6 +39,7 @@ public class UTF16String implements CharSequence, AutoCloseable {
3639 * @return The byte.
3740 */
3841 public byte byteAt (int index ) {
42+ checkIndex (index , byteLength ());
3943 return Native .byteAt (this .pointer , index );
4044 }
4145
@@ -45,6 +49,7 @@ public byte byteAt(int index) {
4549 * @param index The index of the byte.
4650 */
4751 public void setByteAt (int index , byte b ) {
52+ checkIndex (index , byteLength ());
4853 Native .setByteAt (this .pointer , index , b );
4954 }
5055
@@ -56,6 +61,7 @@ public void setByteAt(int index, byte b) {
5661 */
5762 @ Override
5863 public char charAt (int index ) {
64+ checkIndex (index , length ());
5965 return Native .chatAt (this .pointer , index );
6066 }
6167
@@ -65,6 +71,7 @@ public char charAt(int index) {
6571 * @param index The index of the char.
6672 */
6773 public void setCharAt (int index , char c ) {
74+ checkIndex (index , length ());
6875 Native .setCharAt (this .pointer , index , c );
6976 }
7077
@@ -83,9 +90,10 @@ public void append(String string) {
8390 * @param string The string to append.
8491 * @param fromIndex The start offset to append from. This should be Java {@code char}-based index
8592 * in the given string.
86- * @param length The number of character to append.
93+ * @param length The number of character to append from the given string .
8794 */
8895 public void append (String string , int fromIndex , int length ) {
96+ checkStringRange (string , fromIndex , length );
8997 Native .appendPart (this .pointer , string , fromIndex , length );
9098 }
9199
@@ -97,6 +105,7 @@ public void append(String string, int fromIndex, int length) {
97105 * @param string The string to insert.
98106 */
99107 public void insert (int index , String string ) {
108+ checkIndex (index , length ());
100109 Native .insert (this .pointer , string , index );
101110 }
102111
@@ -108,6 +117,9 @@ public void insert(int index, String string) {
108117 * @param toIndex The index to delete to.
109118 */
110119 public void delete (int fromIndex , int toIndex ) {
120+ int size = length ();
121+ checkIndex (fromIndex , size );
122+ checkIndex (toIndex , size + 1 );
111123 Native .deleteChars (this .pointer , fromIndex , toIndex );
112124 }
113125
@@ -118,6 +130,9 @@ public void delete(int fromIndex, int toIndex) {
118130 * @param toIndex The byte index to delete to.
119131 */
120132 public void deleteBytes (int fromIndex , int toIndex ) {
133+ int size = byteLength ();
134+ checkIndex (fromIndex , size );
135+ checkIndex (toIndex , size + 1 );
121136 Native .deleteBytes (this .pointer , fromIndex , toIndex );
122137 }
123138
@@ -130,6 +145,14 @@ public void deleteBytes(int fromIndex, int toIndex) {
130145 * @param str The string to replace with.
131146 */
132147 public void replaceChars (int fromIndex , int toIndex , String str ) {
148+ if (str .length () == 0 ) {
149+ delete (fromIndex , toIndex );
150+ return ;
151+ }
152+
153+ int size = length ();
154+ checkIndex (fromIndex , size );
155+ checkIndex (toIndex , size + 1 );
133156 Native .replaceChars (this .pointer , fromIndex , toIndex , str );
134157 }
135158
@@ -142,6 +165,14 @@ public void replaceChars(int fromIndex, int toIndex, String str) {
142165 * @param str The string to replace with.
143166 */
144167 public void replaceBytes (int fromIndex , int toIndex , String str ) {
168+ if (str .length () == 0 ) {
169+ deleteBytes (fromIndex , toIndex );
170+ return ;
171+ }
172+
173+ int size = byteLength ();
174+ checkIndex (fromIndex , size );
175+ checkIndex (toIndex , size + 1 );
145176 Native .replaceBytes (this .pointer , fromIndex , toIndex , str );
146177 }
147178
@@ -152,6 +183,7 @@ public void replaceBytes(int fromIndex, int toIndex, String str) {
152183 * @return The subsequence.
153184 */
154185 public UTF16String subseqChars (int start ) {
186+ checkIndex (start , length ());
155187 return subseqChars (start , length ());
156188 }
157189
@@ -163,6 +195,9 @@ public UTF16String subseqChars(int start) {
163195 * @return The subsequence.
164196 */
165197 public UTF16String subseqChars (int start , int end ) {
198+ int size = length ();
199+ checkIndex (start , size );
200+ checkIndex (end , size + 1 );
166201 return new UTF16String (Native .substring_chars (this .pointer , start , end ));
167202 }
168203
@@ -173,6 +208,8 @@ public UTF16String subseqChars(int start, int end) {
173208 * @return The subsequence.
174209 */
175210 public UTF16String subseqBytes (int start ) {
211+ int size = byteLength ();
212+ checkIndex (start , size );
176213 return subseqBytes (start , byteLength ());
177214 }
178215
@@ -184,6 +221,9 @@ public UTF16String subseqBytes(int start) {
184221 * @return The subsequence.
185222 */
186223 public UTF16String subseqBytes (int start , int end ) {
224+ int size = byteLength ();
225+ checkIndex (start , size );
226+ checkIndex (end , size + 1 );
187227 return new UTF16String (Native .substring_bytes (this .pointer , start , end ));
188228 }
189229
@@ -194,6 +234,8 @@ public UTF16String subseqBytes(int start, int end) {
194234 * @return The substring.
195235 */
196236 public String substringChars (int start ) {
237+ int size = length ();
238+ checkIndex (start , size );
197239 return substringChars (start , length ());
198240 }
199241
@@ -205,6 +247,9 @@ public String substringChars(int start) {
205247 * @return The substring.
206248 */
207249 public String substringChars (int start , int end ) {
250+ int size = length ();
251+ checkIndex (start , size );
252+ checkIndex (end , size + 1 );
208253 return Native .subjstring_chars (this .pointer , start , end );
209254 }
210255
@@ -215,6 +260,8 @@ public String substringChars(int start, int end) {
215260 * @return The substring.
216261 */
217262 public String substringBytes (int start ) {
263+ int size = byteLength ();
264+ checkIndex (start , size );
218265 return substringBytes (start , length ());
219266 }
220267
@@ -226,6 +273,9 @@ public String substringBytes(int start) {
226273 * @return The substring.
227274 */
228275 public String substringBytes (int start , int end ) {
276+ int size = byteLength ();
277+ checkIndex (start , size );
278+ checkIndex (end , size + 1 );
229279 return Native .subjstring_bytes (this .pointer , start , end );
230280 }
231281
@@ -238,16 +288,6 @@ public int length() {
238288 return Native .length (this .pointer );
239289 }
240290
241- @ Override
242- public CharSequence subSequence (int start , int end ) {
243- final var count = length ();
244- if (end < start || start < 0 || end >= count ) {
245- throw new IndexOutOfBoundsException (
246- "start: " + start + ", end: " + end + ", actual length: " + count );
247- }
248- return subseqChars (start , end );
249- }
250-
251291 /**
252292 * Get the length of this string in terms of Java bytes.
253293 *
@@ -257,6 +297,14 @@ public int byteLength() {
257297 return Native .byteLength (this .pointer );
258298 }
259299
300+ @ Override
301+ public CharSequence subSequence (int start , int end ) {
302+ final var count = length ();
303+ checkIndex (start , count );
304+ checkIndex (start , count + 1 );
305+ return subseqChars (start , end );
306+ }
307+
260308 /** Close this string and release resources. */
261309 @ Override
262310 public void close () {
0 commit comments