mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			391 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			391 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Java
		
	
	
	
/* AttributedStringIterator.java -- Class to iterate over AttributedString
 | 
						|
   Copyright (C) 1998, 1999, 2004, 2005, 2006, 2012 Free Software Foundation, Inc.
 | 
						|
 | 
						|
This file is part of GNU Classpath.
 | 
						|
 | 
						|
GNU Classpath is free software; you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation; either version 2, or (at your option)
 | 
						|
any later version.
 | 
						|
 | 
						|
GNU Classpath is distributed in the hope that it will be useful, but
 | 
						|
WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
						|
General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with GNU Classpath; see the file COPYING.  If not, write to the
 | 
						|
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
						|
02110-1301 USA.
 | 
						|
 | 
						|
Linking this library statically or dynamically with other modules is
 | 
						|
making a combined work based on this library.  Thus, the terms and
 | 
						|
conditions of the GNU General Public License cover the whole
 | 
						|
combination.
 | 
						|
 | 
						|
As a special exception, the copyright holders of this library give you
 | 
						|
permission to link this library with independent modules to produce an
 | 
						|
executable, regardless of the license terms of these independent
 | 
						|
modules, and to copy and distribute the resulting executable under
 | 
						|
terms of your choice, provided that you also meet, for each linked
 | 
						|
independent module, the terms and conditions of the license of that
 | 
						|
module.  An independent module is a module which is not derived from
 | 
						|
or based on this library.  If you modify this library, you may extend
 | 
						|
this exception to your version of the library, but you are not
 | 
						|
obligated to do so.  If you do not wish to do so, delete this
 | 
						|
exception statement from your version. */
 | 
						|
 | 
						|
 | 
						|
package java.text;
 | 
						|
 | 
						|
import java.util.HashMap;
 | 
						|
import java.util.HashSet;
 | 
						|
import java.util.Iterator;
 | 
						|
import java.util.Map;
 | 
						|
import java.util.Set;
 | 
						|
 | 
						|
import static java.text.AttributedCharacterIterator.Attribute;
 | 
						|
 | 
						|
/**
 | 
						|
  * This class implements the AttributedCharacterIterator interface.  It
 | 
						|
  * is used by AttributedString.getIterator().
 | 
						|
  *
 | 
						|
  * @version 0.0
 | 
						|
  *
 | 
						|
  * @author Aaron M. Renn (arenn@urbanophile.com)
 | 
						|
  */
 | 
						|
class AttributedStringIterator implements AttributedCharacterIterator
 | 
						|
{
 | 
						|
 | 
						|
  /*************************************************************************/
 | 
						|
 | 
						|
  /** The character iterator containing the text */
 | 
						|
  private CharacterIterator ci;
 | 
						|
 | 
						|
  /** The list of attributes and ranges */
 | 
						|
  private AttributedString.AttributeRange[] attribs;
 | 
						|
 | 
						|
  /**
 | 
						|
   * The list of attributes that the user is interested in.  We may,
 | 
						|
   * at our option, not return any other attributes.
 | 
						|
   */
 | 
						|
  private Attribute[] restricts;
 | 
						|
 | 
						|
  /*************************************************************************/
 | 
						|
 | 
						|
  /**
 | 
						|
   * Creates a new instance.
 | 
						|
   *
 | 
						|
   * @param sci  an iterator for the string content.
 | 
						|
   * @param attribs  the attribute ranges.
 | 
						|
   * @param beginIndex  the start index.
 | 
						|
   * @param endIndex  the end index.
 | 
						|
   * @param restricts  the attributes that the user is interested in.
 | 
						|
   */
 | 
						|
  AttributedStringIterator(StringCharacterIterator sci,
 | 
						|
                           AttributedString.AttributeRange[] attribs,
 | 
						|
                           int beginIndex, int endIndex,
 | 
						|
                           AttributedCharacterIterator.Attribute[] restricts)
 | 
						|
  {
 | 
						|
    this.ci = new StringCharacterIterator(sci, beginIndex, endIndex);
 | 
						|
    this.attribs = attribs;
 | 
						|
    this.restricts = restricts;
 | 
						|
  }
 | 
						|
 | 
						|
  /*************************************************************************/
 | 
						|
 | 
						|
  // First we have a bunch of stupid redirects.  If StringCharacterIterator
 | 
						|
  // weren't final, I just would have extended that for this class.  Alas, no.
 | 
						|
 | 
						|
  public Object clone()
 | 
						|
  {
 | 
						|
    return(ci.clone());
 | 
						|
  }
 | 
						|
 | 
						|
  public char current()
 | 
						|
  {
 | 
						|
    return(ci.current());
 | 
						|
  }
 | 
						|
 | 
						|
  public char next()
 | 
						|
  {
 | 
						|
    return(ci.next());
 | 
						|
  }
 | 
						|
 | 
						|
  public char previous()
 | 
						|
  {
 | 
						|
    return(ci.previous());
 | 
						|
  }
 | 
						|
 | 
						|
  public char first()
 | 
						|
  {
 | 
						|
    return(ci.first());
 | 
						|
  }
 | 
						|
 | 
						|
  public char last()
 | 
						|
  {
 | 
						|
    return(ci.last());
 | 
						|
  }
 | 
						|
 | 
						|
  public int getIndex()
 | 
						|
  {
 | 
						|
    return(ci.getIndex());
 | 
						|
  }
 | 
						|
 | 
						|
  public char setIndex(int index)
 | 
						|
  {
 | 
						|
    return(ci.setIndex(index));
 | 
						|
  }
 | 
						|
 | 
						|
  public int getBeginIndex()
 | 
						|
  {
 | 
						|
    return(ci.getBeginIndex());
 | 
						|
  }
 | 
						|
 | 
						|
  public int getEndIndex()
 | 
						|
  {
 | 
						|
    return(ci.getEndIndex());
 | 
						|
  }
 | 
						|
 | 
						|
  /*
 | 
						|
   * Here is where the AttributedCharacterIterator methods start.
 | 
						|
   */
 | 
						|
 | 
						|
  /*************************************************************************/
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns a list of all the attribute keys that are defined anywhere
 | 
						|
   * on this string.
 | 
						|
   */
 | 
						|
  public Set<Attribute> getAllAttributeKeys()
 | 
						|
  {
 | 
						|
    HashSet<Attribute> s = new HashSet<Attribute>();
 | 
						|
    if (attribs == null)
 | 
						|
      return(s);
 | 
						|
 | 
						|
    for (int i = 0; i < attribs.length; i++)
 | 
						|
    {
 | 
						|
      if (attribs[i].beginIndex > getEndIndex()
 | 
						|
          || attribs[i].endIndex <= getBeginIndex())
 | 
						|
        continue;
 | 
						|
 | 
						|
      Iterator<? extends Attribute> iter = attribs[i].attribs.keySet().iterator();
 | 
						|
      while (iter.hasNext())
 | 
						|
        {
 | 
						|
          s.add(iter.next());
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return(s);
 | 
						|
  }
 | 
						|
 | 
						|
  /*************************************************************************/
 | 
						|
 | 
						|
  /**
 | 
						|
   * Various methods that determine how far the run extends for various
 | 
						|
   * attribute combinations.
 | 
						|
   */
 | 
						|
 | 
						|
  public int getRunLimit()
 | 
						|
  {
 | 
						|
    return getRunLimit(getAllAttributeKeys());
 | 
						|
  }
 | 
						|
 | 
						|
  public int getRunLimit(Attribute attrib)
 | 
						|
  {
 | 
						|
    HashSet<Attribute> s = new HashSet<Attribute>();
 | 
						|
    s.add(attrib);
 | 
						|
    return(getRunLimit(s));
 | 
						|
  }
 | 
						|
 | 
						|
  public synchronized int getRunLimit(Set<? extends Attribute> attributeSet)
 | 
						|
  {
 | 
						|
    if (attributeSet == null)
 | 
						|
      return ci.getEndIndex();
 | 
						|
 | 
						|
    int current = ci.getIndex();
 | 
						|
    int end = ci.getEndIndex();
 | 
						|
    int limit = current;
 | 
						|
    if (current == end)
 | 
						|
      return end;
 | 
						|
    Map<Attribute,Object> runValues = getAttributes();
 | 
						|
    while (limit < end)
 | 
						|
    {
 | 
						|
      Iterator<? extends Attribute> iterator = attributeSet.iterator();
 | 
						|
      while (iterator.hasNext())
 | 
						|
      {
 | 
						|
        Attribute attributeKey = iterator.next();
 | 
						|
        Object v1 = runValues.get(attributeKey);
 | 
						|
        Object v2 = getAttribute(attributeKey, limit + 1);
 | 
						|
        boolean changed = false;
 | 
						|
        // check for equal or both null, if NO return start
 | 
						|
        if (v1 != null)
 | 
						|
          {
 | 
						|
            changed = !v1.equals(v2);
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            changed = (v2 != null);
 | 
						|
          }
 | 
						|
        if (changed)
 | 
						|
          return limit + 1;
 | 
						|
      }
 | 
						|
      // no differences, so increment limit and next and loop again
 | 
						|
      limit++;
 | 
						|
    }
 | 
						|
    return end;
 | 
						|
  }
 | 
						|
 | 
						|
  /*************************************************************************/
 | 
						|
 | 
						|
  /**
 | 
						|
   * Various methods that determine where the run begins for various
 | 
						|
   * attribute combinations.
 | 
						|
   */
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the index of the first character in the run containing the current
 | 
						|
   * character and defined by all the attributes defined for that character
 | 
						|
   * position.
 | 
						|
   *
 | 
						|
   * @return The run start index.
 | 
						|
   */
 | 
						|
  public int getRunStart()
 | 
						|
  {
 | 
						|
    return(getRunStart(getAttributes().keySet()));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the index of the first character in the run, defined by the
 | 
						|
   * specified attribute, that contains the current character.
 | 
						|
   *
 | 
						|
   * @param attrib  the attribute (<code>null</code> permitted).
 | 
						|
   *
 | 
						|
   * return The index of the first character in the run.
 | 
						|
   */
 | 
						|
  public int getRunStart(Attribute attrib)
 | 
						|
  {
 | 
						|
    if (attrib == null)
 | 
						|
      return ci.getBeginIndex();
 | 
						|
    HashSet<Attribute> s = new HashSet<Attribute>();
 | 
						|
    s.add(attrib);
 | 
						|
    return(getRunStart(s));
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the index of the first character in the run, defined by the
 | 
						|
   * specified attribute set, that contains the current character.
 | 
						|
   *
 | 
						|
   * @param attributeSet  the attribute set (<code>null</code> permitted).
 | 
						|
   *
 | 
						|
   * return The index of the first character in the run.
 | 
						|
   */
 | 
						|
  public int getRunStart(Set<? extends Attribute> attributeSet)
 | 
						|
  {
 | 
						|
    if (attributeSet == null)
 | 
						|
      return ci.getBeginIndex();
 | 
						|
 | 
						|
    int current = ci.getIndex();
 | 
						|
    int begin = ci.getBeginIndex();
 | 
						|
    int start = current;
 | 
						|
    if (start == begin)
 | 
						|
      return begin;
 | 
						|
    Map<Attribute, Object> runValues = getAttributes();
 | 
						|
    int prev = start - 1;
 | 
						|
    while (start > begin)
 | 
						|
    {
 | 
						|
      Iterator<? extends Attribute> iterator = attributeSet.iterator();
 | 
						|
      while (iterator.hasNext())
 | 
						|
      {
 | 
						|
        Attribute attributeKey = iterator.next();
 | 
						|
        Object v1 = runValues.get(attributeKey);
 | 
						|
        Object v2 = getAttribute(attributeKey, prev);
 | 
						|
        boolean changed = false;
 | 
						|
        // check for equal or both null, if NO return start
 | 
						|
        if (v1 != null)
 | 
						|
          {
 | 
						|
            changed = !v1.equals(v2);
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
            changed = (v2 != null);
 | 
						|
          }
 | 
						|
        if (changed)
 | 
						|
          return start;
 | 
						|
      }
 | 
						|
      // no differences, so decrement start and prev and loop again
 | 
						|
      start--;
 | 
						|
      prev--;
 | 
						|
    }
 | 
						|
    return start;
 | 
						|
  }
 | 
						|
 | 
						|
  /*************************************************************************/
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the value for an attribute at the specified position.  If the
 | 
						|
   * attribute key (<code>key</code>) is <code>null</code>, the method returns
 | 
						|
   * <code>null</code>.
 | 
						|
   *
 | 
						|
   * @param key  the key (<code>null</code> permitted).
 | 
						|
   * @param pos  the character position.
 | 
						|
   *
 | 
						|
   * @return The attribute value (possibly <code>null</code>).
 | 
						|
   */
 | 
						|
  private Object getAttribute(AttributedCharacterIterator.Attribute key,
 | 
						|
          int pos)
 | 
						|
  {
 | 
						|
    if (attribs == null)
 | 
						|
      return null;
 | 
						|
    for (int i = attribs.length - 1; i >= 0; i--)
 | 
						|
      {
 | 
						|
        if (pos >= attribs[i].beginIndex && pos < attribs[i].endIndex)
 | 
						|
          {
 | 
						|
            Set<? extends Attribute> keys = attribs[i].attribs.keySet();
 | 
						|
            if (keys.contains(key))
 | 
						|
              {
 | 
						|
                return attribs[i].attribs.get(key);
 | 
						|
              }
 | 
						|
          }
 | 
						|
      }
 | 
						|
    return null;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * Returns the value for an attribute at the current position.  If the
 | 
						|
   * attribute key (<code>key</code>) is <code>null</code>, the method returns
 | 
						|
   * <code>null</code>.
 | 
						|
   *
 | 
						|
   * @param key  the key (<code>null</code> permitted).
 | 
						|
   *
 | 
						|
   * @return The attribute value (possibly <code>null</code>).
 | 
						|
   */
 | 
						|
  public Object getAttribute(AttributedCharacterIterator.Attribute key)
 | 
						|
  {
 | 
						|
    return getAttribute(key, ci.getIndex());
 | 
						|
  }
 | 
						|
 | 
						|
  /*************************************************************************/
 | 
						|
 | 
						|
  /**
 | 
						|
   * Return a list of all the attributes and values defined for this
 | 
						|
   * character
 | 
						|
   */
 | 
						|
  public Map<Attribute,Object> getAttributes()
 | 
						|
  {
 | 
						|
    HashMap<Attribute,Object> m = new HashMap<Attribute,Object>();
 | 
						|
    if (attribs == null)
 | 
						|
      return(m);
 | 
						|
 | 
						|
    for (int i = 0; i < attribs.length; i++)
 | 
						|
      {
 | 
						|
         if ((ci.getIndex() >= attribs[i].beginIndex) &&
 | 
						|
             (ci.getIndex() < attribs[i].endIndex))
 | 
						|
           m.putAll(attribs[i].attribs);
 | 
						|
      }
 | 
						|
 | 
						|
    return(m);
 | 
						|
  }
 | 
						|
 | 
						|
} // class AttributedStringIterator
 |