mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1002 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1002 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Java
		
	
	
	
// DecimalFormat.java - Localized number formatting.
 | 
						|
 | 
						|
/* Copyright (C) 1999, 2000  Free Software Foundation
 | 
						|
 | 
						|
   This file is part of libgcj.
 | 
						|
 | 
						|
This software is copyrighted work licensed under the terms of the
 | 
						|
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 | 
						|
details.  */
 | 
						|
 | 
						|
package java.text;
 | 
						|
 | 
						|
import java.util.Locale;
 | 
						|
import java.util.MissingResourceException;
 | 
						|
import java.util.ResourceBundle;
 | 
						|
import java.io.ObjectInputStream;
 | 
						|
import java.io.IOException;
 | 
						|
 | 
						|
/**
 | 
						|
 * @author Tom Tromey <tromey@cygnus.com>
 | 
						|
 * @date March 4, 1999
 | 
						|
 */
 | 
						|
/* Written using "Java Class Libraries", 2nd edition, plus online
 | 
						|
 * API docs for JDK 1.2 from http://www.javasoft.com.
 | 
						|
 * Status:  Believed complete and correct to 1.2.
 | 
						|
 * Note however that the docs are very unclear about how format parsing
 | 
						|
 * should work.  No doubt there are problems here.
 | 
						|
 */
 | 
						|
 | 
						|
public class DecimalFormat extends NumberFormat
 | 
						|
{
 | 
						|
  // This is a helper for applyPatternWithSymbols.  It reads a prefix
 | 
						|
  // or a suffix.  It can cause some side-effects.
 | 
						|
  private final int scanFix (String pattern, int index, StringBuffer buf,
 | 
						|
			     String patChars, DecimalFormatSymbols syms,
 | 
						|
			     boolean is_suffix)
 | 
						|
    {
 | 
						|
      int len = pattern.length();
 | 
						|
      buf.setLength(0);
 | 
						|
      boolean multiplierSet = false;
 | 
						|
      while (index < len)
 | 
						|
	{
 | 
						|
	  char c = pattern.charAt(index);
 | 
						|
	  if (c == '\'' && index + 1 < len
 | 
						|
	      && pattern.charAt(index + 1) == '\'')
 | 
						|
	    {
 | 
						|
	      buf.append(c);
 | 
						|
	      ++index;
 | 
						|
	    }
 | 
						|
	  else if (c == '\'' && index + 2 < len
 | 
						|
		   && pattern.charAt(index + 2) == '\'')
 | 
						|
	    {
 | 
						|
	      buf.append(pattern.charAt(index + 1));
 | 
						|
	      index += 2;
 | 
						|
	    }
 | 
						|
	  else if (c == '\u00a4')
 | 
						|
	    {
 | 
						|
	      if (index + 1 < len && pattern.charAt(index + 1) == '\u00a4')
 | 
						|
		{
 | 
						|
		  buf.append(syms.getInternationalCurrencySymbol());
 | 
						|
		  ++index;
 | 
						|
		}
 | 
						|
	      else
 | 
						|
		buf.append(syms.getCurrencySymbol());
 | 
						|
	    }
 | 
						|
	  else if (is_suffix && c == syms.getPercent())
 | 
						|
	    {
 | 
						|
	      if (multiplierSet)
 | 
						|
		throw new IllegalArgumentException ("multiplier already set " +
 | 
						|
						    "- index: " + index);
 | 
						|
	      multiplierSet = true;
 | 
						|
	      multiplier = 100;
 | 
						|
	      buf.append(c);
 | 
						|
	    }
 | 
						|
	  else if (is_suffix && c == syms.getPerMill())
 | 
						|
	    {
 | 
						|
	      if (multiplierSet)
 | 
						|
		throw new IllegalArgumentException ("multiplier already set " +
 | 
						|
						    "- index: " + index);
 | 
						|
	      multiplierSet = true;
 | 
						|
	      multiplier = 1000;
 | 
						|
	      buf.append(c);
 | 
						|
	    }
 | 
						|
	  else if (patChars.indexOf(c) != -1)
 | 
						|
	    {
 | 
						|
	      // This is a pattern character.
 | 
						|
	      break;
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    buf.append(c);
 | 
						|
	  ++index;
 | 
						|
	}
 | 
						|
 | 
						|
      return index;
 | 
						|
    }
 | 
						|
 | 
						|
  // A helper which reads a number format.
 | 
						|
  private final int scanFormat (String pattern, int index,
 | 
						|
				String patChars, DecimalFormatSymbols syms,
 | 
						|
				boolean is_positive)
 | 
						|
    {
 | 
						|
      int max = pattern.length();
 | 
						|
 | 
						|
      int countSinceGroup = 0;
 | 
						|
      int zeroCount = 0;
 | 
						|
      boolean saw_group = false;
 | 
						|
 | 
						|
      //
 | 
						|
      // Scan integer part.
 | 
						|
      //
 | 
						|
      while (index < max)
 | 
						|
	{
 | 
						|
	  char c = pattern.charAt(index);
 | 
						|
 | 
						|
	  if (c == syms.getDigit())
 | 
						|
	    {
 | 
						|
	      if (zeroCount > 0)
 | 
						|
		throw new IllegalArgumentException ("digit mark following " +
 | 
						|
						    "zero - index: " + index);
 | 
						|
	      ++countSinceGroup;
 | 
						|
	    }
 | 
						|
	  else if (c == syms.getZeroDigit())
 | 
						|
	    {
 | 
						|
	      ++zeroCount;
 | 
						|
	      ++countSinceGroup;
 | 
						|
	    }
 | 
						|
	  else if (c == syms.getGroupingSeparator())
 | 
						|
	    {
 | 
						|
	      countSinceGroup = 0;
 | 
						|
	      saw_group = true;
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    break;
 | 
						|
 | 
						|
	  ++index;
 | 
						|
	}
 | 
						|
 | 
						|
      // We can only side-effect when parsing the positive format.
 | 
						|
      if (is_positive)
 | 
						|
	{
 | 
						|
	  groupingUsed = saw_group;
 | 
						|
	  groupingSize = (byte) countSinceGroup;
 | 
						|
	  minimumIntegerDigits = zeroCount;
 | 
						|
	}
 | 
						|
 | 
						|
      // Early termination.
 | 
						|
      if (index == max || pattern.charAt(index) == syms.getGroupingSeparator())
 | 
						|
	{
 | 
						|
	  if (is_positive)
 | 
						|
	    decimalSeparatorAlwaysShown = false;
 | 
						|
	  return index;
 | 
						|
	}
 | 
						|
 | 
						|
      if (pattern.charAt(index) == syms.getDecimalSeparator())
 | 
						|
	{
 | 
						|
	  ++index;
 | 
						|
 | 
						|
	  //
 | 
						|
	  // Scan fractional part.
 | 
						|
	  //
 | 
						|
	  int hashCount = 0;
 | 
						|
	  zeroCount = 0;
 | 
						|
	  while (index < max)
 | 
						|
	    {
 | 
						|
	      char c = pattern.charAt(index);
 | 
						|
	      if (c == syms.getZeroDigit())
 | 
						|
		{
 | 
						|
		  if (hashCount > 0)
 | 
						|
		    throw new IllegalArgumentException ("zero mark " +
 | 
						|
					"following digit - index: " + index);
 | 
						|
		  ++zeroCount;
 | 
						|
		}
 | 
						|
	      else if (c == syms.getDigit())
 | 
						|
		{
 | 
						|
		  ++hashCount;
 | 
						|
		}
 | 
						|
	      else if (c != syms.getExponential()
 | 
						|
		       && c != syms.getPatternSeparator()
 | 
						|
		       && patChars.indexOf(c) != -1)
 | 
						|
		throw new IllegalArgumentException ("unexpected special " +
 | 
						|
						"character - index: " + index);
 | 
						|
	      else
 | 
						|
		break;
 | 
						|
 | 
						|
	      ++index;
 | 
						|
	    }
 | 
						|
 | 
						|
	  if (is_positive)
 | 
						|
	    {
 | 
						|
	      maximumFractionDigits = hashCount + zeroCount;
 | 
						|
	      minimumFractionDigits = zeroCount;
 | 
						|
	    }
 | 
						|
 | 
						|
	  if (index == max)
 | 
						|
	    return index;
 | 
						|
	}
 | 
						|
 | 
						|
      if (pattern.charAt(index) == syms.getExponential())
 | 
						|
	{
 | 
						|
	  //
 | 
						|
	  // Scan exponential format.
 | 
						|
	  //
 | 
						|
	  zeroCount = 0;
 | 
						|
	  ++index;
 | 
						|
	  while (index < max)
 | 
						|
	    {
 | 
						|
	      char c = pattern.charAt(index);
 | 
						|
	      if (c == syms.getZeroDigit())
 | 
						|
		++zeroCount;
 | 
						|
	      else if (c == syms.getDigit())
 | 
						|
		{
 | 
						|
		  if (zeroCount > 0)
 | 
						|
		    throw new
 | 
						|
		      IllegalArgumentException ("digit mark following zero " +
 | 
						|
						"in exponent - index: " +
 | 
						|
						index);
 | 
						|
		}
 | 
						|
	      else if (patChars.indexOf(c) != -1)
 | 
						|
		throw new IllegalArgumentException ("unexpected special " +
 | 
						|
						    "character - index: " +
 | 
						|
						    index);
 | 
						|
	      else
 | 
						|
		break;
 | 
						|
 | 
						|
	      ++index;
 | 
						|
	    }
 | 
						|
 | 
						|
	  if (is_positive)
 | 
						|
	    {
 | 
						|
	      useExponentialNotation = true;
 | 
						|
	      minExponentDigits = (byte) zeroCount;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
      return index;
 | 
						|
    }
 | 
						|
 | 
						|
  // This helper function creates a string consisting of all the
 | 
						|
  // characters which can appear in a pattern and must be quoted.
 | 
						|
  private final String patternChars (DecimalFormatSymbols syms)
 | 
						|
    {
 | 
						|
      StringBuffer buf = new StringBuffer ();
 | 
						|
      buf.append(syms.getDecimalSeparator());
 | 
						|
      buf.append(syms.getDigit());
 | 
						|
      buf.append(syms.getExponential());
 | 
						|
      buf.append(syms.getGroupingSeparator());
 | 
						|
      // Adding this one causes pattern application to fail.
 | 
						|
      // Of course, omitting is causes toPattern to fail.
 | 
						|
      // ... but we already have bugs there.  FIXME.
 | 
						|
      // buf.append(syms.getMinusSign());
 | 
						|
      buf.append(syms.getPatternSeparator());
 | 
						|
      buf.append(syms.getPercent());
 | 
						|
      buf.append(syms.getPerMill());
 | 
						|
      buf.append(syms.getZeroDigit());
 | 
						|
      buf.append('\u00a4');
 | 
						|
      return buf.toString();
 | 
						|
    }
 | 
						|
 | 
						|
  private final void applyPatternWithSymbols (String pattern,
 | 
						|
					      DecimalFormatSymbols syms)
 | 
						|
    {
 | 
						|
      // Initialize to the state the parser expects.
 | 
						|
      negativePrefix = "";
 | 
						|
      negativeSuffix = "";
 | 
						|
      positivePrefix = "";
 | 
						|
      positiveSuffix = "";
 | 
						|
      decimalSeparatorAlwaysShown = false;
 | 
						|
      groupingSize = 0;
 | 
						|
      minExponentDigits = 0;
 | 
						|
      multiplier = 1;
 | 
						|
      useExponentialNotation = false;
 | 
						|
      groupingUsed = false;
 | 
						|
      maximumFractionDigits = 0;
 | 
						|
      maximumIntegerDigits = 309;
 | 
						|
      minimumFractionDigits = 0;
 | 
						|
      minimumIntegerDigits = 1;
 | 
						|
 | 
						|
      StringBuffer buf = new StringBuffer ();
 | 
						|
      String patChars = patternChars (syms);
 | 
						|
 | 
						|
      int max = pattern.length();
 | 
						|
      int index = scanFix (pattern, 0, buf, patChars, syms, false);
 | 
						|
      positivePrefix = buf.toString();
 | 
						|
 | 
						|
      index = scanFormat (pattern, index, patChars, syms, true);
 | 
						|
 | 
						|
      index = scanFix (pattern, index, buf, patChars, syms, true);
 | 
						|
      positiveSuffix = buf.toString();
 | 
						|
 | 
						|
      if (index == pattern.length())
 | 
						|
	{
 | 
						|
	  // No negative info.
 | 
						|
	  negativePrefix = null;
 | 
						|
	  negativeSuffix = null;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  if (pattern.charAt(index) != syms.getPatternSeparator())
 | 
						|
	    throw new IllegalArgumentException ("separator character " +
 | 
						|
						"expected - index: " + index);
 | 
						|
 | 
						|
	  index = scanFix (pattern, index + 1, buf, patChars, syms, false);
 | 
						|
	  negativePrefix = buf.toString();
 | 
						|
 | 
						|
	  // We parse the negative format for errors but we don't let
 | 
						|
	  // it side-effect this object.
 | 
						|
	  index = scanFormat (pattern, index, patChars, syms, false);
 | 
						|
 | 
						|
	  index = scanFix (pattern, index, buf, patChars, syms, true);
 | 
						|
	  negativeSuffix = buf.toString();
 | 
						|
 | 
						|
	  if (index != pattern.length())
 | 
						|
	    throw new IllegalArgumentException ("end of pattern expected " +
 | 
						|
						"- index: " + index);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  public void applyLocalizedPattern (String pattern)
 | 
						|
    {
 | 
						|
      // JCL p. 638 claims this throws a ParseException but p. 629
 | 
						|
      // contradicts this.  Empirical tests with patterns of "0,###.0"
 | 
						|
      // and "#.#.#" corroborate the p. 629 statement that an
 | 
						|
      // IllegalArgumentException is thrown.
 | 
						|
      applyPatternWithSymbols (pattern, symbols);
 | 
						|
    }
 | 
						|
 | 
						|
  public void applyPattern (String pattern)
 | 
						|
    {
 | 
						|
      // JCL p. 638 claims this throws a ParseException but p. 629
 | 
						|
      // contradicts this.  Empirical tests with patterns of "0,###.0"
 | 
						|
      // and "#.#.#" corroborate the p. 629 statement that an
 | 
						|
      // IllegalArgumentException is thrown.
 | 
						|
      applyPatternWithSymbols (pattern, nonLocalizedSymbols);
 | 
						|
    }
 | 
						|
 | 
						|
  public Object clone ()
 | 
						|
    {
 | 
						|
      return new DecimalFormat (this);
 | 
						|
    }
 | 
						|
 | 
						|
  private DecimalFormat (DecimalFormat dup)
 | 
						|
    {
 | 
						|
      decimalSeparatorAlwaysShown = dup.decimalSeparatorAlwaysShown;
 | 
						|
      groupingSize = dup.groupingSize;
 | 
						|
      minExponentDigits = dup.minExponentDigits;
 | 
						|
      multiplier = dup.multiplier;
 | 
						|
      negativePrefix = dup.negativePrefix;
 | 
						|
      negativeSuffix = dup.negativeSuffix;
 | 
						|
      positivePrefix = dup.positivePrefix;
 | 
						|
      positiveSuffix = dup.positiveSuffix;
 | 
						|
      symbols = (DecimalFormatSymbols) dup.symbols.clone();
 | 
						|
      useExponentialNotation = dup.useExponentialNotation;
 | 
						|
    }
 | 
						|
 | 
						|
  public DecimalFormat ()
 | 
						|
    {
 | 
						|
      this ("#,##0.###");
 | 
						|
    }
 | 
						|
 | 
						|
  public DecimalFormat (String pattern)
 | 
						|
    {
 | 
						|
      this (pattern, new DecimalFormatSymbols ());
 | 
						|
    }
 | 
						|
 | 
						|
  public DecimalFormat (String pattern, DecimalFormatSymbols symbols)
 | 
						|
    {
 | 
						|
      this.symbols = symbols;
 | 
						|
      applyPattern (pattern);
 | 
						|
    }
 | 
						|
 | 
						|
  private final boolean equals (String s1, String s2)
 | 
						|
    {
 | 
						|
      if (s1 == null || s2 == null)
 | 
						|
	return s1 == s2;
 | 
						|
      return s1.equals(s2);
 | 
						|
    }
 | 
						|
 | 
						|
  public boolean equals (Object obj)
 | 
						|
    {
 | 
						|
      if (! (obj instanceof DecimalFormat))
 | 
						|
	return false;
 | 
						|
      DecimalFormat dup = (DecimalFormat) obj;
 | 
						|
      return (decimalSeparatorAlwaysShown == dup.decimalSeparatorAlwaysShown
 | 
						|
	      && groupingSize == dup.groupingSize
 | 
						|
	      && minExponentDigits == dup.minExponentDigits
 | 
						|
	      && multiplier == dup.multiplier
 | 
						|
	      && equals(negativePrefix, dup.negativePrefix)
 | 
						|
	      && equals(negativeSuffix, dup.negativeSuffix)
 | 
						|
	      && equals(positivePrefix, dup.positivePrefix)
 | 
						|
	      && equals(positiveSuffix, dup.positiveSuffix)
 | 
						|
	      && symbols.equals(dup.symbols)
 | 
						|
	      && useExponentialNotation == dup.useExponentialNotation);
 | 
						|
    }
 | 
						|
 | 
						|
  public StringBuffer format (double number, StringBuffer dest,
 | 
						|
			      FieldPosition fieldPos)
 | 
						|
    {
 | 
						|
      // A very special case.
 | 
						|
      if (Double.isNaN(number))
 | 
						|
	{
 | 
						|
	  dest.append(symbols.getNaN());
 | 
						|
	  if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
 | 
						|
	    {
 | 
						|
	      int index = dest.length();
 | 
						|
	      fieldPos.setBeginIndex(index - symbols.getNaN().length());
 | 
						|
	      fieldPos.setEndIndex(index);
 | 
						|
	    }
 | 
						|
	  return dest;
 | 
						|
	}
 | 
						|
 | 
						|
      boolean is_neg = number < 0;
 | 
						|
      if (is_neg)
 | 
						|
	{
 | 
						|
	  if (negativePrefix != null)
 | 
						|
	    dest.append(negativePrefix);
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      dest.append(symbols.getMinusSign());
 | 
						|
	      dest.append(positivePrefix);
 | 
						|
	    }
 | 
						|
	  number = - number;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	dest.append(positivePrefix);
 | 
						|
 | 
						|
      int integerBeginIndex = dest.length();
 | 
						|
      int integerEndIndex = 0;
 | 
						|
      if (Double.isInfinite (number))
 | 
						|
	{
 | 
						|
	  dest.append(symbols.getInfinity());
 | 
						|
	  integerEndIndex = dest.length();
 | 
						|
	}
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  number *= multiplier;
 | 
						|
 | 
						|
	  // Compute exponent.
 | 
						|
	  long exponent = 0;
 | 
						|
	  double baseNumber;
 | 
						|
	  if (useExponentialNotation)
 | 
						|
	    {
 | 
						|
	      exponent = (long) (Math.log(number) / Math.log(10));
 | 
						|
	      if (minimumIntegerDigits > 0)
 | 
						|
		exponent -= minimumIntegerDigits - 1;
 | 
						|
	      baseNumber = (long) (number / Math.pow(10.0, exponent));
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    baseNumber = number;
 | 
						|
 | 
						|
	  // Round to the correct number of digits.
 | 
						|
	  baseNumber += 5 * Math.pow(10.0, - maximumFractionDigits - 1);
 | 
						|
 | 
						|
	  int index = dest.length();
 | 
						|
	  double intPart = Math.floor(baseNumber);
 | 
						|
	  int count = 0;
 | 
						|
	  while (count < maximumIntegerDigits
 | 
						|
		 && (intPart > 0 || count < minimumIntegerDigits))
 | 
						|
	    {
 | 
						|
	      long dig = (long) (intPart % 10);
 | 
						|
	      intPart = Math.floor(intPart / 10);
 | 
						|
 | 
						|
	      // Append group separator if required.
 | 
						|
	      if (groupingUsed && count > 0 && count % groupingSize == 0)
 | 
						|
		dest.insert(index, symbols.getGroupingSeparator());
 | 
						|
 | 
						|
	      dest.insert(index, (char) (symbols.getZeroDigit() + dig));
 | 
						|
 | 
						|
	      ++count;
 | 
						|
	    }
 | 
						|
 | 
						|
	  integerEndIndex = dest.length();
 | 
						|
 | 
						|
	  int decimal_index = integerEndIndex;
 | 
						|
	  int consecutive_zeros = 0;
 | 
						|
	  int total_digits = 0;
 | 
						|
 | 
						|
	  // Strip integer part from NUMBER.
 | 
						|
	  double fracPart = baseNumber - Math.floor(baseNumber);
 | 
						|
	  for (count = 0;
 | 
						|
	       count < maximumFractionDigits
 | 
						|
		 && (fracPart != 0 || count < minimumFractionDigits);
 | 
						|
	       ++count)
 | 
						|
	    {
 | 
						|
	      ++total_digits;
 | 
						|
	      fracPart *= 10;
 | 
						|
	      long dig = (long) fracPart;
 | 
						|
	      if (dig == 0)
 | 
						|
		++consecutive_zeros;
 | 
						|
	      else
 | 
						|
		consecutive_zeros = 0;
 | 
						|
	      dest.append((char) (symbols.getZeroDigit() + dig));
 | 
						|
 | 
						|
	      // Strip integer part from FRACPART.
 | 
						|
	      fracPart = fracPart - Math.floor (fracPart);
 | 
						|
	    }
 | 
						|
 | 
						|
	  // Strip extraneous trailing `0's.  We can't always detect
 | 
						|
	  // these in the loop.
 | 
						|
	  int extra_zeros = Math.min (consecutive_zeros,
 | 
						|
				      total_digits - minimumFractionDigits);
 | 
						|
	  if (extra_zeros > 0)
 | 
						|
	    {
 | 
						|
	      dest.setLength(dest.length() - extra_zeros);
 | 
						|
	      total_digits -= extra_zeros;
 | 
						|
	    }
 | 
						|
 | 
						|
	  // If required, add the decimal symbol.
 | 
						|
	  if (decimalSeparatorAlwaysShown
 | 
						|
	      || total_digits > 0)
 | 
						|
	    {
 | 
						|
	      dest.insert(decimal_index, symbols.getDecimalSeparator());
 | 
						|
	      if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
 | 
						|
		{
 | 
						|
		  fieldPos.setBeginIndex(decimal_index + 1);
 | 
						|
		  fieldPos.setEndIndex(dest.length());
 | 
						|
		}
 | 
						|
	    }
 | 
						|
 | 
						|
	  // Finally, print the exponent.
 | 
						|
	  if (useExponentialNotation)
 | 
						|
	    {
 | 
						|
	      dest.append(symbols.getExponential());
 | 
						|
	      dest.append(exponent < 0 ? '-' : '+');
 | 
						|
	      index = dest.length();
 | 
						|
	      for (count = 0;
 | 
						|
		   exponent > 0 || count < minExponentDigits;
 | 
						|
		   ++count)
 | 
						|
		{
 | 
						|
		  long dig = exponent % 10;
 | 
						|
		  exponent /= 10;
 | 
						|
		  dest.insert(index, (char) (symbols.getZeroDigit() + dig));
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
      if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
 | 
						|
	{
 | 
						|
	  fieldPos.setBeginIndex(integerBeginIndex);
 | 
						|
	  fieldPos.setEndIndex(integerEndIndex);
 | 
						|
	}
 | 
						|
 | 
						|
      dest.append((is_neg && negativeSuffix != null)
 | 
						|
		  ? negativeSuffix
 | 
						|
		  : positiveSuffix);
 | 
						|
      return dest;
 | 
						|
    }
 | 
						|
 | 
						|
  public StringBuffer format (long number, StringBuffer dest,
 | 
						|
			      FieldPosition fieldPos)
 | 
						|
    {
 | 
						|
      // If using exponential notation, we just format as a double.
 | 
						|
      if (useExponentialNotation)
 | 
						|
	return format ((double) number, dest, fieldPos);
 | 
						|
 | 
						|
      boolean is_neg = number < 0;
 | 
						|
      if (is_neg)
 | 
						|
	{
 | 
						|
	  if (negativePrefix != null)
 | 
						|
	    dest.append(negativePrefix);
 | 
						|
	  else
 | 
						|
	    {
 | 
						|
	      dest.append(symbols.getMinusSign());
 | 
						|
	      dest.append(positivePrefix);
 | 
						|
	    }
 | 
						|
	  number = - number;
 | 
						|
	}
 | 
						|
      else
 | 
						|
	dest.append(positivePrefix);
 | 
						|
 | 
						|
      int integerBeginIndex = dest.length();
 | 
						|
      int index = dest.length();
 | 
						|
      int count = 0;
 | 
						|
      while (count < maximumIntegerDigits
 | 
						|
	     && (number > 0 || count < minimumIntegerDigits))
 | 
						|
	{
 | 
						|
	  long dig = number % 10;
 | 
						|
	  number /= 10;
 | 
						|
	  // NUMBER and DIG will be less than 0 if the original number
 | 
						|
	  // was the most negative long.
 | 
						|
	  if (dig < 0)
 | 
						|
	    {
 | 
						|
	      dig = - dig;
 | 
						|
	      number = - number;
 | 
						|
	    }
 | 
						|
 | 
						|
	  // Append group separator if required.
 | 
						|
	  if (groupingUsed && count > 0 && count % groupingSize == 0)
 | 
						|
	    dest.insert(index, symbols.getGroupingSeparator());
 | 
						|
 | 
						|
	  dest.insert(index, (char) (symbols.getZeroDigit() + dig));
 | 
						|
 | 
						|
	  ++count;
 | 
						|
	}
 | 
						|
 | 
						|
      if (fieldPos != null && fieldPos.getField() == INTEGER_FIELD)
 | 
						|
	{
 | 
						|
	  fieldPos.setBeginIndex(integerBeginIndex);
 | 
						|
	  fieldPos.setEndIndex(dest.length());
 | 
						|
	}
 | 
						|
 | 
						|
      if (decimalSeparatorAlwaysShown || minimumFractionDigits > 0)
 | 
						|
	{
 | 
						|
	  dest.append(symbols.getDecimalSeparator());
 | 
						|
	  if (fieldPos != null && fieldPos.getField() == FRACTION_FIELD)
 | 
						|
	    {
 | 
						|
	      fieldPos.setBeginIndex(dest.length());
 | 
						|
	      fieldPos.setEndIndex(dest.length() + minimumFractionDigits);
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
      for (count = 0; count < minimumFractionDigits; ++count)
 | 
						|
	dest.append(symbols.getZeroDigit());
 | 
						|
 | 
						|
      dest.append((is_neg && negativeSuffix != null)
 | 
						|
		  ? negativeSuffix
 | 
						|
		  : positiveSuffix);
 | 
						|
      return dest;
 | 
						|
    }
 | 
						|
 | 
						|
  public DecimalFormatSymbols getDecimalFormatSymbols ()
 | 
						|
    {
 | 
						|
      return symbols;
 | 
						|
    }
 | 
						|
 | 
						|
  public int getGroupingSize ()
 | 
						|
    {
 | 
						|
      return groupingSize;
 | 
						|
    }
 | 
						|
 | 
						|
  public int getMultiplier ()
 | 
						|
    {
 | 
						|
      return multiplier;
 | 
						|
    }
 | 
						|
 | 
						|
  public String getNegativePrefix ()
 | 
						|
    {
 | 
						|
      return negativePrefix;
 | 
						|
    }
 | 
						|
 | 
						|
  public String getNegativeSuffix ()
 | 
						|
    {
 | 
						|
      return negativeSuffix;
 | 
						|
    }
 | 
						|
 | 
						|
  public String getPositivePrefix ()
 | 
						|
    {
 | 
						|
      return positivePrefix;
 | 
						|
    }
 | 
						|
 | 
						|
  public String getPositiveSuffix ()
 | 
						|
    {
 | 
						|
      return positiveSuffix;
 | 
						|
    }
 | 
						|
 | 
						|
  public int hashCode ()
 | 
						|
    {
 | 
						|
      int hash = (negativeSuffix.hashCode() ^ negativePrefix.hashCode()
 | 
						|
		  ^positivePrefix.hashCode() ^ positiveSuffix.hashCode());
 | 
						|
      // FIXME.
 | 
						|
      return hash;
 | 
						|
    }
 | 
						|
 | 
						|
  public boolean isDecimalSeparatorAlwaysShown ()
 | 
						|
    {
 | 
						|
      return decimalSeparatorAlwaysShown;
 | 
						|
    }
 | 
						|
 | 
						|
  public Number parse (String str, ParsePosition pos)
 | 
						|
    {
 | 
						|
      // Our strategy is simple: copy the text into a buffer,
 | 
						|
      // translating or omitting locale-specific information.  Then
 | 
						|
      // let Double or Long convert the number for us.
 | 
						|
 | 
						|
      boolean is_neg = false;
 | 
						|
      int index = pos.getIndex();
 | 
						|
      StringBuffer buf = new StringBuffer ();
 | 
						|
 | 
						|
      // We have to check both prefixes, because one might be empty.
 | 
						|
      // We want to pick the longest prefix that matches.
 | 
						|
      boolean got_pos = str.startsWith(positivePrefix, index);
 | 
						|
      String np = (negativePrefix != null
 | 
						|
		   ? negativePrefix
 | 
						|
		   : positivePrefix + symbols.getMinusSign());
 | 
						|
      boolean got_neg = str.startsWith(np, index);
 | 
						|
 | 
						|
      if (got_pos && got_neg)
 | 
						|
	{
 | 
						|
	  // By checking this way, we preserve ambiguity in the case
 | 
						|
	  // where the negative format differs only in suffix.  We
 | 
						|
	  // check this again later.
 | 
						|
	  if (np.length() > positivePrefix.length())
 | 
						|
	    {
 | 
						|
	      is_neg = true;
 | 
						|
	      index += np.length();
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    index += positivePrefix.length();
 | 
						|
	}
 | 
						|
      else if (got_neg)
 | 
						|
	{
 | 
						|
	  is_neg = true;
 | 
						|
	  index += np.length();
 | 
						|
	}
 | 
						|
      else if (got_pos)
 | 
						|
	index += positivePrefix.length();
 | 
						|
      else
 | 
						|
	{
 | 
						|
	  pos.setErrorIndex (index);
 | 
						|
	  return null;
 | 
						|
	}
 | 
						|
 | 
						|
      // FIXME: handle Inf and NaN.
 | 
						|
 | 
						|
      // FIXME: do we have to respect minimum/maxmimum digit stuff?
 | 
						|
      // What about leading zeros?  What about multiplier?
 | 
						|
 | 
						|
      int start_index = index;
 | 
						|
      int max = str.length();
 | 
						|
      char zero = symbols.getZeroDigit();
 | 
						|
      int last_group = -1;
 | 
						|
      boolean int_part = true;
 | 
						|
      boolean exp_part = false;
 | 
						|
      for (; index < max; ++index)
 | 
						|
	{
 | 
						|
	  char c = str.charAt(index);
 | 
						|
 | 
						|
	  // FIXME: what about grouping size?
 | 
						|
	  if (groupingUsed && c == symbols.getGroupingSeparator())
 | 
						|
	    {
 | 
						|
	      if (last_group != -1
 | 
						|
		  && (index - last_group) % groupingSize != 0)
 | 
						|
		{
 | 
						|
		  pos.setErrorIndex(index);
 | 
						|
		  return null;
 | 
						|
		}
 | 
						|
	      last_group = index;
 | 
						|
	    }
 | 
						|
	  else if (c >= zero && c <= zero + 9)
 | 
						|
	    {
 | 
						|
	      buf.append((char) (c - zero + '0'));
 | 
						|
	      exp_part = false;
 | 
						|
	    }
 | 
						|
	  else if (parseIntegerOnly)
 | 
						|
	    break;
 | 
						|
	  else if (c == symbols.getDecimalSeparator())
 | 
						|
	    {
 | 
						|
	      if (last_group != -1
 | 
						|
		  && (index - last_group) % groupingSize != 0)
 | 
						|
		{
 | 
						|
		  pos.setErrorIndex(index);
 | 
						|
		  return null;
 | 
						|
		}
 | 
						|
	      buf.append('.');
 | 
						|
	      int_part = false;
 | 
						|
	    }
 | 
						|
	  else if (c == symbols.getExponential())
 | 
						|
	    {
 | 
						|
	      buf.append('E');
 | 
						|
	      int_part = false;
 | 
						|
	      exp_part = true;
 | 
						|
	    }
 | 
						|
	  else if (exp_part
 | 
						|
		   && (c == '+' || c == '-' || c == symbols.getMinusSign()))
 | 
						|
	    {
 | 
						|
	      // For exponential notation.
 | 
						|
	      buf.append(c);
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
 | 
						|
      if (index == start_index)
 | 
						|
	{
 | 
						|
	  // Didn't see any digits.
 | 
						|
	  pos.setErrorIndex(index);
 | 
						|
	  return null;
 | 
						|
	}
 | 
						|
 | 
						|
      // Check the suffix.  We must do this before converting the
 | 
						|
      // buffer to a number to handle the case of a number which is
 | 
						|
      // the most negative Long.
 | 
						|
      boolean got_pos_suf = str.startsWith(positiveSuffix, index);
 | 
						|
      String ns = (negativePrefix == null ? positiveSuffix : negativeSuffix);
 | 
						|
      boolean got_neg_suf = str.startsWith(ns, index);
 | 
						|
      if (is_neg)
 | 
						|
	{
 | 
						|
	  if (! got_neg_suf)
 | 
						|
	    {
 | 
						|
	      pos.setErrorIndex(index);
 | 
						|
	      return null;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      else if (got_pos && got_neg && got_neg_suf)
 | 
						|
	{
 | 
						|
	  is_neg = true;
 | 
						|
	}
 | 
						|
      else if (got_pos != got_pos_suf && got_neg != got_neg_suf)
 | 
						|
	{
 | 
						|
	  pos.setErrorIndex(index);
 | 
						|
	  return null;
 | 
						|
	}
 | 
						|
 | 
						|
      String suffix = is_neg ? ns : positiveSuffix;
 | 
						|
      if (is_neg)
 | 
						|
	buf.insert(0, '-');
 | 
						|
 | 
						|
      String t = buf.toString();
 | 
						|
      Number result = null;
 | 
						|
      try
 | 
						|
	{
 | 
						|
	  result = new Long (t);
 | 
						|
	}
 | 
						|
      catch (NumberFormatException x1)
 | 
						|
	{
 | 
						|
	  try
 | 
						|
	    {
 | 
						|
	      result = new Double (t);
 | 
						|
	    }
 | 
						|
	  catch (NumberFormatException x2)
 | 
						|
	    {
 | 
						|
	    }
 | 
						|
	}
 | 
						|
      if (result == null)
 | 
						|
	{
 | 
						|
	  pos.setErrorIndex(index);
 | 
						|
	  return null;
 | 
						|
	}
 | 
						|
 | 
						|
      pos.setIndex(index + suffix.length());
 | 
						|
 | 
						|
      return result;
 | 
						|
    }
 | 
						|
 | 
						|
  public void setDecimalFormatSymbols (DecimalFormatSymbols newSymbols)
 | 
						|
    {
 | 
						|
      symbols = newSymbols;
 | 
						|
    }
 | 
						|
 | 
						|
  public void setDecimalSeparatorAlwaysShown (boolean newValue)
 | 
						|
    {
 | 
						|
      decimalSeparatorAlwaysShown = newValue;
 | 
						|
    }
 | 
						|
 | 
						|
  public void setGroupingSize (int groupSize)
 | 
						|
    {
 | 
						|
      groupingSize = (byte) groupSize;
 | 
						|
    }
 | 
						|
 | 
						|
  public void setMaximumFractionDigits (int newValue)
 | 
						|
    {
 | 
						|
      maximumFractionDigits = Math.min(newValue, 340);
 | 
						|
    }
 | 
						|
 | 
						|
  public void setMaximumIntegerDigits (int newValue)
 | 
						|
    {
 | 
						|
      maximumIntegerDigits = Math.min(newValue, 309);
 | 
						|
    }
 | 
						|
 | 
						|
  public void setMinimumFractionDigits (int newValue)
 | 
						|
    {
 | 
						|
      minimumFractionDigits = Math.min(newValue, 340);
 | 
						|
    }
 | 
						|
 | 
						|
  public void setMinimumIntegerDigits (int newValue)
 | 
						|
    {
 | 
						|
      minimumIntegerDigits = Math.min(newValue, 309);
 | 
						|
    }
 | 
						|
 | 
						|
  public void setMultiplier (int newValue)
 | 
						|
    {
 | 
						|
      multiplier = newValue;
 | 
						|
    }
 | 
						|
 | 
						|
  public void setNegativePrefix (String newValue)
 | 
						|
    {
 | 
						|
      negativePrefix = newValue;
 | 
						|
    }
 | 
						|
 | 
						|
  public void setNegativeSuffix (String newValue)
 | 
						|
    {
 | 
						|
      negativeSuffix = newValue;
 | 
						|
    }
 | 
						|
 | 
						|
  public void setPositivePrefix (String newValue)
 | 
						|
    {
 | 
						|
      positivePrefix = newValue;
 | 
						|
    }
 | 
						|
 | 
						|
  public void setPositiveSuffix (String newValue)
 | 
						|
    {
 | 
						|
      positiveSuffix = newValue;
 | 
						|
    }
 | 
						|
 | 
						|
  private final void quoteFix (StringBuffer buf, String text, String patChars)
 | 
						|
    {
 | 
						|
      int len = text.length();
 | 
						|
      for (int index = 0; index < len; ++index)
 | 
						|
	{
 | 
						|
	  char c = text.charAt(index);
 | 
						|
	  if (patChars.indexOf(c) != -1)
 | 
						|
	    {
 | 
						|
	      buf.append('\'');
 | 
						|
	      buf.append(c);
 | 
						|
	      buf.append('\'');
 | 
						|
	    }
 | 
						|
	  else
 | 
						|
	    buf.append(c);
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
  private final String computePattern (DecimalFormatSymbols syms)
 | 
						|
    {
 | 
						|
      StringBuffer mainPattern = new StringBuffer ();
 | 
						|
      // We have to at least emit a zero for the minimum number of
 | 
						|
      // digits.  Past that we need hash marks up to the grouping
 | 
						|
      // separator (and one beyond).
 | 
						|
      int total_digits = Math.max(minimumIntegerDigits,
 | 
						|
				  groupingUsed ? groupingSize + 1: 0);
 | 
						|
      for (int i = 0; i < total_digits - minimumIntegerDigits; ++i)
 | 
						|
	mainPattern.append(syms.getDigit());
 | 
						|
      for (int i = total_digits - minimumIntegerDigits; i < total_digits; ++i)
 | 
						|
	mainPattern.append(syms.getZeroDigit());
 | 
						|
      // Inserting the gropuing operator afterwards is easier.
 | 
						|
      if (groupingUsed)
 | 
						|
	mainPattern.insert(mainPattern.length() - groupingSize,
 | 
						|
			   syms.getGroupingSeparator());
 | 
						|
      // See if we need decimal info.
 | 
						|
      if (minimumFractionDigits > 0 || maximumFractionDigits > 0
 | 
						|
	  || decimalSeparatorAlwaysShown)
 | 
						|
	mainPattern.append(syms.getDecimalSeparator());
 | 
						|
      for (int i = 0; i < minimumFractionDigits; ++i)
 | 
						|
	mainPattern.append(syms.getZeroDigit());
 | 
						|
      for (int i = minimumFractionDigits; i < maximumFractionDigits; ++i)
 | 
						|
	mainPattern.append(syms.getDigit());
 | 
						|
      if (useExponentialNotation)
 | 
						|
	{
 | 
						|
	  mainPattern.append(syms.getExponential());
 | 
						|
	  for (int i = 0; i < minExponentDigits; ++i)
 | 
						|
	    mainPattern.append(syms.getZeroDigit());
 | 
						|
	  if (minExponentDigits == 0)
 | 
						|
	    mainPattern.append(syms.getDigit());
 | 
						|
	}
 | 
						|
 | 
						|
      String main = mainPattern.toString();
 | 
						|
      String patChars = patternChars (syms);
 | 
						|
      mainPattern.setLength(0);
 | 
						|
 | 
						|
      quoteFix (mainPattern, positivePrefix, patChars);
 | 
						|
      mainPattern.append(main);
 | 
						|
      quoteFix (mainPattern, positiveSuffix, patChars);
 | 
						|
 | 
						|
      if (negativePrefix != null)
 | 
						|
	{
 | 
						|
	  quoteFix (mainPattern, negativePrefix, patChars);
 | 
						|
	  mainPattern.append(main);
 | 
						|
	  quoteFix (mainPattern, negativeSuffix, patChars);
 | 
						|
	}
 | 
						|
 | 
						|
      return mainPattern.toString();
 | 
						|
    }
 | 
						|
 | 
						|
  public String toLocalizedPattern ()
 | 
						|
    {
 | 
						|
      return computePattern (symbols);
 | 
						|
    }
 | 
						|
 | 
						|
  public String toPattern ()
 | 
						|
    {
 | 
						|
      return computePattern (nonLocalizedSymbols);
 | 
						|
    }
 | 
						|
 | 
						|
  // These names are fixed by the serialization spec.
 | 
						|
  private boolean decimalSeparatorAlwaysShown;
 | 
						|
  private byte groupingSize;
 | 
						|
  private byte minExponentDigits;
 | 
						|
  private int multiplier;
 | 
						|
  private String negativePrefix;
 | 
						|
  private String negativeSuffix;
 | 
						|
  private String positivePrefix;
 | 
						|
  private String positiveSuffix;
 | 
						|
  private int serialVersionOnStream = 1;
 | 
						|
  private DecimalFormatSymbols symbols;
 | 
						|
  private boolean useExponentialNotation;
 | 
						|
  private static final long serialVersionUID = 864413376551465018L;
 | 
						|
 | 
						|
  private void readObject(ObjectInputStream stream)
 | 
						|
    throws IOException, ClassNotFoundException
 | 
						|
  {
 | 
						|
    stream.defaultReadObject();
 | 
						|
    if (serialVersionOnStream < 1)
 | 
						|
      {
 | 
						|
        useExponentialNotation = false;
 | 
						|
	serialVersionOnStream = 1;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  // The locale-independent pattern symbols happen to be the same as
 | 
						|
  // the US symbols.
 | 
						|
  private static final DecimalFormatSymbols nonLocalizedSymbols
 | 
						|
    = new DecimalFormatSymbols (Locale.US);
 | 
						|
}
 |