001/* ======================================================================== 002 * JCommon : a free general purpose class library for the Java(tm) platform 003 * ======================================================================== 004 * 005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jcommon/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 025 * in the United States and other countries.] 026 * 027 * ---------------------- 028 * LineBreakIterator.java 029 * ---------------------- 030 * (C)opyright 2003, by Thomas Morgner and Contributors. 031 * 032 * Original Author: Thomas Morgner; 033 * Contributor(s): David Gilbert (for Object Refinery Limited); 034 * 035 * $Id: LineBreakIterator.java,v 1.4 2005/11/03 09:55:26 mungady Exp $ 036 * 037 * Changes 038 * ------- 039 * 13-03-2003 : Initial version 040 */ 041package org.jfree.util; 042 043import java.util.Iterator; 044 045/** 046 * An iterator that breaks text into lines. 047 * The result is equal to BufferedReader.readLine(). 048 * 049 * @author Thomas Morgner 050 */ 051public class LineBreakIterator implements Iterator 052{ 053 /** A useful constant. */ 054 public static final int DONE = -1; 055 056 /** Storage for the text. */ 057 private char[] text; 058 059 /** The current position. */ 060 private int position; 061 062 /** 063 * Default constructor. 064 */ 065 public LineBreakIterator() 066 { 067 setText(""); 068 } 069 070 /** 071 * Creates a new line break iterator. 072 * 073 * @param text the text to be broken up. 074 */ 075 public LineBreakIterator(final String text) 076 { 077 setText(text); 078 } 079 080 /** 081 * Returns the position of the next break. 082 * 083 * @return A position. 084 */ 085 public synchronized int nextPosition() 086 { 087 if (this.text == null) 088 { 089 return DONE; 090 } 091 if (this.position == DONE) 092 { 093 return DONE; 094 } 095 096 // recognize \n, \r, \r\n 097 098 final int nChars = this.text.length; 099 int nextChar = this.position; 100 101 for (;;) 102 { 103 if (nextChar >= nChars) 104 { 105 /* End of text reached */ 106 this.position = DONE; 107 return DONE; 108 } 109 110 boolean eol = false; 111 char c = 0; 112 int i; 113 114 // search the next line break, either \n or \r 115 for (i = nextChar; i < nChars; i++) 116 { 117 c = this.text[i]; 118 if ((c == '\n') || (c == '\r')) 119 { 120 eol = true; 121 break; 122 } 123 } 124 125 nextChar = i; 126 if (eol) 127 { 128 nextChar++; 129 if (c == '\r') 130 { 131 if ((nextChar < nChars) && (this.text[nextChar] == '\n')) 132 { 133 nextChar++; 134 } 135 } 136 this.position = nextChar; 137 return (this.position); 138 } 139 } 140 } 141 142 /** 143 * Same like next(), but returns the End-Of-Text as 144 * if there was a linebreak added (Reader.readLine() compatible) 145 * 146 * @return The next position. 147 */ 148 public int nextWithEnd() 149 { 150 final int pos = this.position; 151 if (pos == DONE) 152 { 153 return DONE; 154 } 155 if (pos == this.text.length) 156 { 157 this.position = DONE; 158 return DONE; 159 } 160 final int retval = nextPosition(); 161 if (retval == DONE) 162 { 163 return this.text.length; 164 } 165 return retval; 166 } 167 168 /** 169 * Returns the text to be broken up. 170 * 171 * @return The text. 172 */ 173 public String getText() 174 { 175 return new String(this.text); 176 } 177 178 /** 179 * Sets the text to be broken up. 180 * 181 * @param text the text. 182 */ 183 public void setText(final String text) 184 { 185 this.position = 0; 186 this.text = text.toCharArray(); 187 } 188 189 /** 190 * Returns <tt>true</tt> if the iteration has more elements. (In other 191 * words, returns <tt>true</tt> if <tt>next</tt> would return an element 192 * rather than throwing an exception.) 193 * 194 * @return <tt>true</tt> if the iterator has more elements. 195 */ 196 public boolean hasNext() 197 { 198 return (this.position != DONE); 199 } 200 201 /** 202 * Returns the next element in the iteration. 203 * 204 * @return the next element in the iteration. 205 */ 206 public Object next() 207 { 208 if (this.position == DONE) 209 { 210 // allready at the end ... 211 return null; 212 } 213 214 final int lastFound = this.position; 215 int pos = nextWithEnd(); 216 if (pos == DONE) 217 { 218 // the end of the text has been reached ... 219 return new String(this.text, lastFound, this.text.length - lastFound); 220 } 221 222 // step one char back 223 if (pos > 0) 224 { 225 final int end = lastFound; 226 for (; ((pos) > end) && ((this.text[pos - 1] == '\n') || this.text[pos - 1] == '\r'); pos--) 227 { 228 // search the end of the current linebreak sequence .. 229 } 230 } 231 //System.out.println ("text: " + new String (text)); 232 //System.out.println ("pos: " + pos + " lastFound: " + lastFound); 233 return new String(this.text, lastFound, pos - lastFound); 234 } 235 236 /** 237 * 238 * Removes from the underlying collection the last element returned by the 239 * iterator (optional operation). This method can be called only once per 240 * call to <tt>next</tt>. The behavior of an iterator is unspecified if 241 * the underlying collection is modified while the iteration is in 242 * progress in any way other than by calling this method. 243 * 244 * @exception UnsupportedOperationException if the <tt>remove</tt> 245 * operation is not supported by this Iterator. 246 * @exception IllegalStateException if the <tt>next</tt> method has not 247 * yet been called, or the <tt>remove</tt> method has already 248 * been called after the last call to the <tt>next</tt> 249 * method. 250 */ 251 public void remove() 252 { 253 throw new UnsupportedOperationException("This iterator is read-only."); 254 } 255}