1 /*
2  * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 /*
27  * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
28  * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
29  *
30  * The original version of this source code and documentation
31  * is copyrighted and owned by Taligent, Inc., a wholly-owned
32  * subsidiary of IBM. These materials are provided under terms
33  * of a License Agreement between Taligent and Sun. This technology
34  * is protected by multiple US and International patents.
35  *
36  * This notice and attribution to Taligent may not be removed.
37  * Taligent is a registered trademark of Taligent, Inc.
38  *
39  */
40 
41 package java.text;
42 
43 /**
44  * {@code StringCharacterIterator} implements the
45  * {@code CharacterIterator} protocol for a {@code String}.
46  * The {@code StringCharacterIterator} class iterates over the
47  * entire {@code String}.
48  *
49  * @see CharacterIterator
50  * @since 1.1
51  */
52 
53 public final class StringCharacterIterator implements CharacterIterator
54 {
55     private String text;
56     private int begin;
57     private int end;
58     // invariant: begin <= pos <= end
59     private int pos;
60 
61     /**
62      * Constructs an iterator with an initial index of 0.
63      *
64      * @param text the {@code String} to be iterated over
65      */
StringCharacterIterator(String text)66     public StringCharacterIterator(String text)
67     {
68         this(text, 0);
69     }
70 
71     /**
72      * Constructs an iterator with the specified initial index.
73      *
74      * @param  text   The String to be iterated over
75      * @param  pos    Initial iterator position
76      */
StringCharacterIterator(String text, int pos)77     public StringCharacterIterator(String text, int pos)
78     {
79     this(text, 0, text.length(), pos);
80     }
81 
82     /**
83      * Constructs an iterator over the given range of the given string, with the
84      * index set at the specified position.
85      *
86      * @param  text   The String to be iterated over
87      * @param  begin  Index of the first character
88      * @param  end    Index of the character following the last character
89      * @param  pos    Initial iterator position
90      */
StringCharacterIterator(String text, int begin, int end, int pos)91     public StringCharacterIterator(String text, int begin, int end, int pos) {
92         if (text == null)
93             throw new NullPointerException();
94         this.text = text;
95 
96         if (begin < 0 || begin > end || end > text.length())
97             throw new IllegalArgumentException("Invalid substring range");
98 
99         if (pos < begin || pos > end)
100             throw new IllegalArgumentException("Invalid position");
101 
102         this.begin = begin;
103         this.end = end;
104         this.pos = pos;
105     }
106 
107     /**
108      * Reset this iterator to point to a new string.  This package-visible
109      * method is used by other java.text classes that want to avoid allocating
110      * new StringCharacterIterator objects every time their setText method
111      * is called.
112      *
113      * @param  text   The String to be iterated over
114      * @since 1.2
115      */
setText(String text)116     public void setText(String text) {
117         if (text == null)
118             throw new NullPointerException();
119         this.text = text;
120         this.begin = 0;
121         this.end = text.length();
122         this.pos = 0;
123     }
124 
125     /**
126      * Implements CharacterIterator.first() for String.
127      * @see CharacterIterator#first
128      */
first()129     public char first()
130     {
131         pos = begin;
132         return current();
133     }
134 
135     /**
136      * Implements CharacterIterator.last() for String.
137      * @see CharacterIterator#last
138      */
last()139     public char last()
140     {
141         if (end != begin) {
142             pos = end - 1;
143         } else {
144             pos = end;
145         }
146         return current();
147      }
148 
149     /**
150      * Implements CharacterIterator.setIndex() for String.
151      * @see CharacterIterator#setIndex
152      */
setIndex(int p)153     public char setIndex(int p)
154     {
155     if (p < begin || p > end)
156             throw new IllegalArgumentException("Invalid index");
157         pos = p;
158         return current();
159     }
160 
161     /**
162      * Implements CharacterIterator.current() for String.
163      * @see CharacterIterator#current
164      */
current()165     public char current()
166     {
167         if (pos >= begin && pos < end) {
168             return text.charAt(pos);
169         }
170         else {
171             return DONE;
172         }
173     }
174 
175     /**
176      * Implements CharacterIterator.next() for String.
177      * @see CharacterIterator#next
178      */
next()179     public char next()
180     {
181         if (pos < end - 1) {
182             pos++;
183             return text.charAt(pos);
184         }
185         else {
186             pos = end;
187             return DONE;
188         }
189     }
190 
191     /**
192      * Implements CharacterIterator.previous() for String.
193      * @see CharacterIterator#previous
194      */
previous()195     public char previous()
196     {
197         if (pos > begin) {
198             pos--;
199             return text.charAt(pos);
200         }
201         else {
202             return DONE;
203         }
204     }
205 
206     /**
207      * Implements CharacterIterator.getBeginIndex() for String.
208      * @see CharacterIterator#getBeginIndex
209      */
getBeginIndex()210     public int getBeginIndex()
211     {
212         return begin;
213     }
214 
215     /**
216      * Implements CharacterIterator.getEndIndex() for String.
217      * @see CharacterIterator#getEndIndex
218      */
getEndIndex()219     public int getEndIndex()
220     {
221         return end;
222     }
223 
224     /**
225      * Implements CharacterIterator.getIndex() for String.
226      * @see CharacterIterator#getIndex
227      */
getIndex()228     public int getIndex()
229     {
230         return pos;
231     }
232 
233     /**
234      * Compares the equality of two StringCharacterIterator objects.
235      * @param obj the StringCharacterIterator object to be compared with.
236      * @return true if the given obj is the same as this
237      * StringCharacterIterator object; false otherwise.
238      */
equals(Object obj)239     public boolean equals(Object obj)
240     {
241         if (this == obj)
242             return true;
243         if (!(obj instanceof StringCharacterIterator that))
244             return false;
245 
246         if (hashCode() != that.hashCode())
247             return false;
248         if (!text.equals(that.text))
249             return false;
250         if (pos != that.pos || begin != that.begin || end != that.end)
251             return false;
252         return true;
253     }
254 
255     /**
256      * Computes a hashcode for this iterator.
257      * @return A hash code
258      */
hashCode()259     public int hashCode()
260     {
261         return text.hashCode() ^ pos ^ begin ^ end;
262     }
263 
264     /**
265      * Creates a copy of this iterator.
266      * @return A copy of this
267      */
clone()268     public Object clone()
269     {
270         try {
271             StringCharacterIterator other
272             = (StringCharacterIterator) super.clone();
273             return other;
274         }
275         catch (CloneNotSupportedException e) {
276             throw new InternalError(e);
277         }
278     }
279 
280 }
281