1 /*
   2  * Copyright (c) 1996, 2013, 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</code> implements the
  45  * <code>CharacterIterator</code> protocol for a <code>String</code>.
  46  * The <code>StringCharacterIterator</code> class iterates over the
  47  * entire <code>String</code>.
  48  *
  49  * @see CharacterIterator
  50  */
  51 
  52 public final class StringCharacterIterator implements CharacterIterator
  53 {
  54     private String text;
  55     private int begin;
  56     private int end;
  57     // invariant: begin <= pos <= end
  58     private int pos;
  59 
  60     /**
  61      * Constructs an iterator with an initial index of 0.
  62      *
  63      * @param text the {@code String} to be iterated over
  64      */
  65     public StringCharacterIterator(String text)
  66     {
  67         this(text, 0);
  68     }
  69 
  70     /**
  71      * Constructs an iterator with the specified initial index.
  72      *
  73      * @param  text   The String to be iterated over
  74      * @param  pos    Initial iterator position
  75      */
  76     public StringCharacterIterator(String text, int pos)
  77     {
  78     this(text, 0, text.length(), pos);
  79     }
  80 
  81     /**
  82      * Constructs an iterator over the given range of the given string, with the
  83      * index set at the specified position.
  84      *
  85      * @param  text   The String to be iterated over
  86      * @param  begin  Index of the first character
  87      * @param  end    Index of the character following the last character
  88      * @param  pos    Initial iterator position
  89      */
  90     public StringCharacterIterator(String text, int begin, int end, int pos) {
  91         if (text == null)
  92             throw new NullPointerException();
  93         this.text = text;
  94 
  95         if (begin < 0 || begin > end || end > text.length())
  96             throw new IllegalArgumentException("Invalid substring range");
  97 
  98         if (pos < begin || pos > end)
  99             throw new IllegalArgumentException("Invalid position");
 100 
 101         this.begin = begin;
 102         this.end = end;
 103         this.pos = pos;
 104     }
 105 
 106     /**
 107      * Reset this iterator to point to a new string.  This package-visible
 108      * method is used by other java.text classes that want to avoid allocating
 109      * new StringCharacterIterator objects every time their setText method
 110      * is called.
 111      *
 112      * @param  text   The String to be iterated over
 113      * @since 1.2
 114      */
 115     public void setText(String text) {
 116         if (text == null)
 117             throw new NullPointerException();
 118         this.text = text;
 119         this.begin = 0;
 120         this.end = text.length();
 121         this.pos = 0;
 122     }
 123 
 124     /**
 125      * Implements CharacterIterator.first() for String.
 126      * @see CharacterIterator#first
 127      */
 128     public char first()
 129     {
 130         pos = begin;
 131         return current();
 132     }
 133 
 134     /**
 135      * Implements CharacterIterator.last() for String.
 136      * @see CharacterIterator#last
 137      */
 138     public char last()
 139     {
 140         if (end != begin) {
 141             pos = end - 1;
 142         } else {
 143             pos = end;
 144         }
 145         return current();
 146      }
 147 
 148     /**
 149      * Implements CharacterIterator.setIndex() for String.
 150      * @see CharacterIterator#setIndex
 151      */
 152     public char setIndex(int p)
 153     {
 154     if (p < begin || p > end)
 155             throw new IllegalArgumentException("Invalid index");
 156         pos = p;
 157         return current();
 158     }
 159 
 160     /**
 161      * Implements CharacterIterator.current() for String.
 162      * @see CharacterIterator#current
 163      */
 164     public char current()
 165     {
 166         if (pos >= begin && pos < end) {
 167             return text.charAt(pos);
 168         }
 169         else {
 170             return DONE;
 171         }
 172     }
 173 
 174     /**
 175      * Implements CharacterIterator.next() for String.
 176      * @see CharacterIterator#next
 177      */
 178     public char next()
 179     {
 180         if (pos < end - 1) {
 181             pos++;
 182             return text.charAt(pos);
 183         }
 184         else {
 185             pos = end;
 186             return DONE;
 187         }
 188     }
 189 
 190     /**
 191      * Implements CharacterIterator.previous() for String.
 192      * @see CharacterIterator#previous
 193      */
 194     public char previous()
 195     {
 196         if (pos > begin) {
 197             pos--;
 198             return text.charAt(pos);
 199         }
 200         else {
 201             return DONE;
 202         }
 203     }
 204 
 205     /**
 206      * Implements CharacterIterator.getBeginIndex() for String.
 207      * @see CharacterIterator#getBeginIndex
 208      */
 209     public int getBeginIndex()
 210     {
 211         return begin;
 212     }
 213 
 214     /**
 215      * Implements CharacterIterator.getEndIndex() for String.
 216      * @see CharacterIterator#getEndIndex
 217      */
 218     public int getEndIndex()
 219     {
 220         return end;
 221     }
 222 
 223     /**
 224      * Implements CharacterIterator.getIndex() for String.
 225      * @see CharacterIterator#getIndex
 226      */
 227     public int getIndex()
 228     {
 229         return pos;
 230     }
 231 
 232     /**
 233      * Compares the equality of two StringCharacterIterator objects.
 234      * @param obj the StringCharacterIterator object to be compared with.
 235      * @return true if the given obj is the same as this
 236      * StringCharacterIterator object; false otherwise.
 237      */
 238     public boolean equals(Object obj)
 239     {
 240         if (this == obj)
 241             return true;
 242         if (!(obj instanceof StringCharacterIterator))
 243             return false;
 244 
 245         StringCharacterIterator that = (StringCharacterIterator) obj;
 246 
 247         if (hashCode() != that.hashCode())
 248             return false;
 249         if (!text.equals(that.text))
 250             return false;
 251         if (pos != that.pos || begin != that.begin || end != that.end)
 252             return false;
 253         return true;
 254     }
 255 
 256     /**
 257      * Computes a hashcode for this iterator.
 258      * @return A hash code
 259      */
 260     public int hashCode()
 261     {
 262         return text.hashCode() ^ pos ^ begin ^ end;
 263     }
 264 
 265     /**
 266      * Creates a copy of this iterator.
 267      * @return A copy of this
 268      */
 269     public Object clone()
 270     {
 271         try {
 272             StringCharacterIterator other
 273             = (StringCharacterIterator) super.clone();
 274             return other;
 275         }
 276         catch (CloneNotSupportedException e) {
 277             throw new InternalError(e);
 278         }
 279     }
 280 
 281 }