From 2045f2ea52ed9e593372405f24ae01a63875205f Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 5 Sep 2001 00:00:55 +0000 Subject: * java/text/SimpleDateFormat.java: Re-merged with Classpath. * gnu/gcj/text/LocaleData.java, gnu/gcj/text/LocaleData_en.java, gnu/gcj/text/LocaleData_en_US.java: Removed. * java/text/DateFormatSymbols.java (clone): Use Classpath implementation. (equals): Simplified. (DateFormatSymbols): Look in gnu.java.locale for information. (DateFormatSymbols(DateFormatSymbols)): Removed. (safeGetResource): Removed. (DateFormatSymbols): Throws MissingResourceException. (ampmsDefault, erasDefault, localPatternCharsDefault, monthsDefault, shortMonthsDefault, shortWeekdaysDefault, weekdaysDefault, zoneStringsDefault): Removed. * java/text/Collator.java (getAvailableLocales): Use modified Classpath implementation. (getInstance): Look in gnu.java.locale for information. (clone): Rewrote. * java/text/MessageFormat.java: Reindented. (clone): Rewrote. * java/text/FieldPosition.java: Merged with Classpath. * java/text/ParsePosition.java: Merged with Classpath. * java/text/Format.java: Merged with Classpath. * java/text/StringCharacterIterator.java (StringCharacterIterator(StringCharacterIterator,int,int)): New constructor from Classpath. * java/text/Annotation.java, java/text/AttributedCharacterIterator.java, java/text/AttributedString.java, java/text/AttributedStringIterator.java: New from Classpath. * java/text/CharacterIterator.java: Copied from Classpath. * java/text/ChoiceFormat.java: Reindented. (clone): Removed. * gnu/java/text/BaseBreakIterator.java, gnu/java/text/CharacterBreakIterator.java, gnu/java/text/LineBreakIterator.java, gnu/java/text/LocaleData_en.java, gnu/java/text/LocaleData_en_US.java, gnu/java/text/SentenceBreakIterator.java, gnu/java/text/WordBreakIterator.java: Renamed from gnu/gcj/text/*. * gnu/gcj/text/BaseBreakIterator.java (last): Advance past final character. * java/text/BreakIterator.java (getAvailableLocales): Use Classpath implementation. (getInstance): Look in gnu.java.locale for information. (getCharacterInstance, getLineInstance, getSentenceInstance, getWordInstance): Look in gnu.java.text for implementations. * java/text/DecimalFormatSymbols.java: Reindented (clone): Use Classpath implementation. (DecimalFormatSymbols(DecimalFormatSymbols)): Removed. (DecimalFormatSymbols(Locale)): Look in gnu.java.locale for information. * java/text/DateFormat.java: Merged with Classpath. (getAvailableLocales): Use Classpath implementation. (format(Object,StringBuffer,FieldPosition)): Minor cleanup. (computeInstance): Look in gnu.java.locale for information. * java/text/NumberFormat.java: Reindented. (computeInstance): Look in gnu.java.locale for information. (getAvailableLocales): Use implementation from Classpath. (setMaximumIntegerDigits): Likewise. (setMinimumIntegerDigits): Likewise. (setMaximumFractionDigits): Likewise. (clone): Removed. * java/text/DecimalFormat.java: Reindented. * gnu/java/locale/LocaleInformation_en.java: Copied from Classpath. * gnu/java/locale/LocaleInformation_en_US.java: Copied from Classpath. * Makefile.in: Rebuilt. * Makefile.am (ordinary_java_source_files): Added all new files. (ordinary_java_source_files): Renamed or removed gnu/gcj/text/*. * java/security/spec/AlgorithmParameterSpec.java, java/security/spec/KeySpec.java: Re-merged with Classpath. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@45390 138bc75d-0d04-0410-961f-82ee72b054a4 --- libjava/ChangeLog | 71 + libjava/Makefile.am | 22 +- libjava/Makefile.in | 45 +- libjava/gnu/gcj/text/BaseBreakIterator.java | 82 - libjava/gnu/gcj/text/CharacterBreakIterator.java | 188 --- libjava/gnu/gcj/text/LineBreakIterator.java | 168 -- libjava/gnu/gcj/text/LocaleData.java | 25 - libjava/gnu/gcj/text/LocaleData_en.java | 92 -- libjava/gnu/gcj/text/LocaleData_en_US.java | 81 - libjava/gnu/gcj/text/SentenceBreakIterator.java | 226 --- libjava/gnu/gcj/text/WordBreakIterator.java | 224 --- libjava/gnu/java/locale/LocaleInformation_de.java | 4 +- libjava/gnu/java/locale/LocaleInformation_en.java | 408 ++--- .../gnu/java/locale/LocaleInformation_en_US.java | 112 ++ libjava/gnu/java/locale/LocaleInformation_nl.java | 38 +- libjava/gnu/java/text/BaseBreakIterator.java | 101 ++ libjava/gnu/java/text/CharacterBreakIterator.java | 205 +++ libjava/gnu/java/text/LineBreakIterator.java | 185 +++ libjava/gnu/java/text/SentenceBreakIterator.java | 243 +++ libjava/gnu/java/text/WordBreakIterator.java | 241 +++ libjava/java/text/Annotation.java | 102 ++ libjava/java/text/AttributedCharacterIterator.java | 333 ++++ libjava/java/text/AttributedString.java | 431 +++++ libjava/java/text/AttributedStringIterator.java | 351 ++++ libjava/java/text/BreakIterator.java | 213 ++- libjava/java/text/CharacterIterator.java | 169 +- libjava/java/text/ChoiceFormat.java | 697 +++++--- libjava/java/text/Collator.java | 277 +++- libjava/java/text/DateFormat.java | 322 +++- libjava/java/text/DateFormatSymbols.java | 381 +++-- libjava/java/text/DecimalFormat.java | 1701 ++++++++++---------- libjava/java/text/DecimalFormatSymbols.java | 647 +++++--- libjava/java/text/FieldPosition.java | 146 +- libjava/java/text/Format.java | 138 +- libjava/java/text/MessageFormat.java | 33 +- libjava/java/text/NumberFormat.java | 591 +++++-- libjava/java/text/ParsePosition.java | 121 +- libjava/java/text/SimpleDateFormat.java | 1 + libjava/java/text/StringCharacterIterator.java | 360 ++++- 39 files changed, 6519 insertions(+), 3256 deletions(-) delete mode 100644 libjava/gnu/gcj/text/BaseBreakIterator.java delete mode 100644 libjava/gnu/gcj/text/CharacterBreakIterator.java delete mode 100644 libjava/gnu/gcj/text/LineBreakIterator.java delete mode 100644 libjava/gnu/gcj/text/LocaleData.java delete mode 100644 libjava/gnu/gcj/text/LocaleData_en.java delete mode 100644 libjava/gnu/gcj/text/LocaleData_en_US.java delete mode 100644 libjava/gnu/gcj/text/SentenceBreakIterator.java delete mode 100644 libjava/gnu/gcj/text/WordBreakIterator.java create mode 100644 libjava/gnu/java/locale/LocaleInformation_en_US.java create mode 100644 libjava/gnu/java/text/BaseBreakIterator.java create mode 100644 libjava/gnu/java/text/CharacterBreakIterator.java create mode 100644 libjava/gnu/java/text/LineBreakIterator.java create mode 100644 libjava/gnu/java/text/SentenceBreakIterator.java create mode 100644 libjava/gnu/java/text/WordBreakIterator.java create mode 100644 libjava/java/text/Annotation.java create mode 100644 libjava/java/text/AttributedCharacterIterator.java create mode 100644 libjava/java/text/AttributedString.java create mode 100644 libjava/java/text/AttributedStringIterator.java diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 46741e15527..1a542aaa22f 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,5 +1,76 @@ 2001-09-04 Tom Tromey + * java/text/SimpleDateFormat.java: Re-merged with Classpath. + * gnu/gcj/text/LocaleData.java, gnu/gcj/text/LocaleData_en.java, + gnu/gcj/text/LocaleData_en_US.java: Removed. + * java/text/DateFormatSymbols.java (clone): Use Classpath + implementation. + (equals): Simplified. + (DateFormatSymbols): Look in gnu.java.locale for information. + (DateFormatSymbols(DateFormatSymbols)): Removed. + (safeGetResource): Removed. + (DateFormatSymbols): Throws MissingResourceException. + (ampmsDefault, erasDefault, localPatternCharsDefault, + monthsDefault, shortMonthsDefault, shortWeekdaysDefault, + weekdaysDefault, zoneStringsDefault): Removed. + * java/text/Collator.java (getAvailableLocales): Use modified + Classpath implementation. + (getInstance): Look in gnu.java.locale for information. + (clone): Rewrote. + * java/text/MessageFormat.java: Reindented. + (clone): Rewrote. + * java/text/FieldPosition.java: Merged with Classpath. + * java/text/ParsePosition.java: Merged with Classpath. + * java/text/Format.java: Merged with Classpath. + * java/text/StringCharacterIterator.java + (StringCharacterIterator(StringCharacterIterator,int,int)): New + constructor from Classpath. + * java/text/Annotation.java, + java/text/AttributedCharacterIterator.java, + java/text/AttributedString.java, + java/text/AttributedStringIterator.java: New from Classpath. + * java/text/CharacterIterator.java: Copied from Classpath. + * java/text/ChoiceFormat.java: Reindented. + (clone): Removed. + * gnu/java/text/BaseBreakIterator.java, + gnu/java/text/CharacterBreakIterator.java, + gnu/java/text/LineBreakIterator.java, + gnu/java/text/LocaleData_en.java, + gnu/java/text/LocaleData_en_US.java, + gnu/java/text/SentenceBreakIterator.java, + gnu/java/text/WordBreakIterator.java: Renamed from gnu/gcj/text/*. + * gnu/gcj/text/BaseBreakIterator.java (last): Advance past final + character. + * java/text/BreakIterator.java (getAvailableLocales): Use + Classpath implementation. + (getInstance): Look in gnu.java.locale for information. + (getCharacterInstance, getLineInstance, getSentenceInstance, + getWordInstance): Look in gnu.java.text for implementations. + * java/text/DecimalFormatSymbols.java: Reindented + (clone): Use Classpath implementation. + (DecimalFormatSymbols(DecimalFormatSymbols)): Removed. + (DecimalFormatSymbols(Locale)): Look in gnu.java.locale for + information. + * java/text/DateFormat.java: Merged with Classpath. + (getAvailableLocales): Use Classpath implementation. + (format(Object,StringBuffer,FieldPosition)): Minor cleanup. + (computeInstance): Look in gnu.java.locale for information. + * java/text/NumberFormat.java: Reindented. + (computeInstance): Look in gnu.java.locale for information. + (getAvailableLocales): Use implementation from Classpath. + (setMaximumIntegerDigits): Likewise. + (setMinimumIntegerDigits): Likewise. + (setMaximumFractionDigits): Likewise. + (clone): Removed. + * java/text/DecimalFormat.java: Reindented. + * gnu/java/locale/LocaleInformation_en.java: Copied from Classpath. + * gnu/java/locale/LocaleInformation_en_US.java: Copied from Classpath. + * Makefile.in: Rebuilt. + * Makefile.am (ordinary_java_source_files): Added all new files. + (ordinary_java_source_files): Renamed or removed gnu/gcj/text/*. + * java/security/spec/AlgorithmParameterSpec.java, + java/security/spec/KeySpec.java: Re-merged with Classpath. + Fix for PR libgcj/4213: * Makefile.am (ordinary_java_source_files): Added new file. * gnu/gcj/text/LocaleData.java: New file. diff --git a/libjava/Makefile.am b/libjava/Makefile.am index d80838a3bd1..65748dd684c 100644 --- a/libjava/Makefile.am +++ b/libjava/Makefile.am @@ -1123,14 +1123,6 @@ gnu/gcj/protocol/jar/Handler.java \ gnu/gcj/runtime/FileDeleter.java \ gnu/gcj/runtime/FirstThread.java \ gnu/gcj/runtime/VMClassLoader.java \ -gnu/gcj/text/BaseBreakIterator.java \ -gnu/gcj/text/CharacterBreakIterator.java \ -gnu/gcj/text/LineBreakIterator.java \ -gnu/gcj/text/LocaleData.java \ -gnu/gcj/text/LocaleData_en.java \ -gnu/gcj/text/LocaleData_en_US.java \ -gnu/gcj/text/SentenceBreakIterator.java \ -gnu/gcj/text/WordBreakIterator.java \ gnu/java/io/ClassLoaderObjectInputStream.java \ gnu/java/io/NullOutputStream.java \ gnu/java/io/ObjectIdentityWrapper.java \ @@ -1141,10 +1133,20 @@ gnu/java/locale/Calendar.java \ gnu/java/locale/Calendar_de.java \ gnu/java/locale/Calendar_en.java \ gnu/java/locale/Calendar_nl.java \ +gnu/java/locale/LocaleInformation.java \ +gnu/java/locale/LocaleInformation_de.java \ +gnu/java/locale/LocaleInformation_en.java \ +gnu/java/locale/LocaleInformation_en_US.java \ +gnu/java/locale/LocaleInformation_nl.java \ gnu/java/security/provider/DefaultPolicy.java \ gnu/java/security/provider/Gnu.java \ gnu/java/security/provider/SHA.java \ gnu/java/security/provider/SHA1PRNG.java \ +gnu/java/text/BaseBreakIterator.java \ +gnu/java/text/CharacterBreakIterator.java \ +gnu/java/text/LineBreakIterator.java \ +gnu/java/text/SentenceBreakIterator.java \ +gnu/java/text/WordBreakIterator.java \ gnu/java/util/DoubleEnumeration.java \ java/lang/ref/PhantomReference.java \ java/lang/ref/Reference.java \ @@ -1333,6 +1335,10 @@ java/sql/Struct.java \ java/sql/Time.java \ java/sql/Timestamp.java \ java/sql/Types.java \ +java/text/Annotation.java \ +java/text/AttributedCharacterIterator.java \ +java/text/AttributedString.java \ +java/text/AttributedStringIterator.java \ java/text/BreakIterator.java \ java/text/CharacterIterator.java \ java/text/ChoiceFormat.java \ diff --git a/libjava/Makefile.in b/libjava/Makefile.in index b888b649525..ff899e7a747 100644 --- a/libjava/Makefile.in +++ b/libjava/Makefile.in @@ -873,14 +873,6 @@ gnu/gcj/protocol/jar/Handler.java \ gnu/gcj/runtime/FileDeleter.java \ gnu/gcj/runtime/FirstThread.java \ gnu/gcj/runtime/VMClassLoader.java \ -gnu/gcj/text/BaseBreakIterator.java \ -gnu/gcj/text/CharacterBreakIterator.java \ -gnu/gcj/text/LineBreakIterator.java \ -gnu/gcj/text/LocaleData.java \ -gnu/gcj/text/LocaleData_en.java \ -gnu/gcj/text/LocaleData_en_US.java \ -gnu/gcj/text/SentenceBreakIterator.java \ -gnu/gcj/text/WordBreakIterator.java \ gnu/java/io/ClassLoaderObjectInputStream.java \ gnu/java/io/NullOutputStream.java \ gnu/java/io/ObjectIdentityWrapper.java \ @@ -891,10 +883,20 @@ gnu/java/locale/Calendar.java \ gnu/java/locale/Calendar_de.java \ gnu/java/locale/Calendar_en.java \ gnu/java/locale/Calendar_nl.java \ +gnu/java/locale/LocaleInformation.java \ +gnu/java/locale/LocaleInformation_de.java \ +gnu/java/locale/LocaleInformation_en.java \ +gnu/java/locale/LocaleInformation_en_US.java \ +gnu/java/locale/LocaleInformation_nl.java \ gnu/java/security/provider/DefaultPolicy.java \ gnu/java/security/provider/Gnu.java \ gnu/java/security/provider/SHA.java \ gnu/java/security/provider/SHA1PRNG.java \ +gnu/java/text/BaseBreakIterator.java \ +gnu/java/text/CharacterBreakIterator.java \ +gnu/java/text/LineBreakIterator.java \ +gnu/java/text/SentenceBreakIterator.java \ +gnu/java/text/WordBreakIterator.java \ gnu/java/util/DoubleEnumeration.java \ java/lang/ref/PhantomReference.java \ java/lang/ref/Reference.java \ @@ -1083,6 +1085,10 @@ java/sql/Struct.java \ java/sql/Time.java \ java/sql/Timestamp.java \ java/sql/Types.java \ +java/text/Annotation.java \ +java/text/AttributedCharacterIterator.java \ +java/text/AttributedString.java \ +java/text/AttributedStringIterator.java \ java/text/BreakIterator.java \ java/text/CharacterIterator.java \ java/text/ChoiceFormat.java \ @@ -1491,14 +1497,7 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \ .deps/gnu/gcj/protocol/jar/Handler.P \ .deps/gnu/gcj/runtime/FileDeleter.P .deps/gnu/gcj/runtime/FirstThread.P \ .deps/gnu/gcj/runtime/VMClassLoader.P \ -.deps/gnu/gcj/runtime/natFirstThread.P \ -.deps/gnu/gcj/text/BaseBreakIterator.P \ -.deps/gnu/gcj/text/CharacterBreakIterator.P \ -.deps/gnu/gcj/text/LineBreakIterator.P .deps/gnu/gcj/text/LocaleData.P \ -.deps/gnu/gcj/text/LocaleData_en.P \ -.deps/gnu/gcj/text/LocaleData_en_US.P \ -.deps/gnu/gcj/text/SentenceBreakIterator.P \ -.deps/gnu/gcj/text/WordBreakIterator.P .deps/gnu/gcj/xlib/Clip.P \ +.deps/gnu/gcj/runtime/natFirstThread.P .deps/gnu/gcj/xlib/Clip.P \ .deps/gnu/gcj/xlib/Colormap.P .deps/gnu/gcj/xlib/Display.P \ .deps/gnu/gcj/xlib/Drawable.P .deps/gnu/gcj/xlib/Font.P \ .deps/gnu/gcj/xlib/GC.P .deps/gnu/gcj/xlib/Pixmap.P \ @@ -1543,6 +1542,11 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \ .deps/gnu/java/lang/reflect/TypeSignature.P \ .deps/gnu/java/locale/Calendar.P .deps/gnu/java/locale/Calendar_de.P \ .deps/gnu/java/locale/Calendar_en.P .deps/gnu/java/locale/Calendar_nl.P \ +.deps/gnu/java/locale/LocaleInformation.P \ +.deps/gnu/java/locale/LocaleInformation_de.P \ +.deps/gnu/java/locale/LocaleInformation_en.P \ +.deps/gnu/java/locale/LocaleInformation_en_US.P \ +.deps/gnu/java/locale/LocaleInformation_nl.P \ .deps/gnu/java/rmi/dgc/DGCImpl.P .deps/gnu/java/rmi/dgc/DGCImpl_Skel.P \ .deps/gnu/java/rmi/dgc/DGCImpl_Stub.P \ .deps/gnu/java/rmi/registry/RegistryImpl.P \ @@ -1565,6 +1569,11 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \ .deps/gnu/java/security/provider/Gnu.P \ .deps/gnu/java/security/provider/SHA.P \ .deps/gnu/java/security/provider/SHA1PRNG.P \ +.deps/gnu/java/text/BaseBreakIterator.P \ +.deps/gnu/java/text/CharacterBreakIterator.P \ +.deps/gnu/java/text/LineBreakIterator.P \ +.deps/gnu/java/text/SentenceBreakIterator.P \ +.deps/gnu/java/text/WordBreakIterator.P \ .deps/gnu/java/util/DoubleEnumeration.P .deps/interpret.P \ .deps/java/applet/Applet.P .deps/java/applet/AppletContext.P \ .deps/java/applet/AppletStub.P .deps/java/applet/AudioClip.P \ @@ -2024,6 +2033,10 @@ DEP_FILES = .deps/$(srcdir)/$(CONVERT_DIR)/gen-from-JIS.P \ .deps/java/sql/SQLOutput.P .deps/java/sql/SQLWarning.P \ .deps/java/sql/Statement.P .deps/java/sql/Struct.P \ .deps/java/sql/Time.P .deps/java/sql/Timestamp.P .deps/java/sql/Types.P \ +.deps/java/text/Annotation.P \ +.deps/java/text/AttributedCharacterIterator.P \ +.deps/java/text/AttributedString.P \ +.deps/java/text/AttributedStringIterator.P \ .deps/java/text/BreakIterator.P .deps/java/text/CharacterIterator.P \ .deps/java/text/ChoiceFormat.P \ .deps/java/text/CollationElementIterator.P \ diff --git a/libjava/gnu/gcj/text/BaseBreakIterator.java b/libjava/gnu/gcj/text/BaseBreakIterator.java deleted file mode 100644 index 8c20d46d47c..00000000000 --- a/libjava/gnu/gcj/text/BaseBreakIterator.java +++ /dev/null @@ -1,82 +0,0 @@ -// Base class for default BreakIterators. - -/* Copyright (C) 1999 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 gnu.gcj.text; - -import java.text.BreakIterator; -import java.text.CharacterIterator; - -/** - * @author Tom Tromey - * @date March 22, 1999 - */ - -public abstract class BaseBreakIterator extends BreakIterator -{ - public int current () - { - return iter.getIndex(); - } - - public int first () - { - iter.first(); - return iter.getBeginIndex(); - } - - public int following (int pos) - { - int save = iter.getIndex(); - iter.setIndex(pos); - int r = next (); - iter.setIndex(save); - return r; - } - - public CharacterIterator getText () - { - return iter; - } - - public int last () - { - iter.last(); - return iter.getEndIndex(); - } - - public int next (int n) - { - int r = iter.getIndex (); - if (n > 0) - { - while (n > 0 && r != DONE) - { - r = next (); - --n; - } - } - else if (n < 0) - { - while (n < 0 && r != DONE) - { - r = previous (); - ++n; - } - } - return r; - } - - public void setText (CharacterIterator newText) - { - iter = newText; - } - - protected CharacterIterator iter; -} diff --git a/libjava/gnu/gcj/text/CharacterBreakIterator.java b/libjava/gnu/gcj/text/CharacterBreakIterator.java deleted file mode 100644 index ba087ccc461..00000000000 --- a/libjava/gnu/gcj/text/CharacterBreakIterator.java +++ /dev/null @@ -1,188 +0,0 @@ -// Default character BreakIterator. - -/* Copyright (C) 1999 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 gnu.gcj.text; - -import java.text.BreakIterator; -import java.text.CharacterIterator; - -/** - * @author Tom Tromey - * @date March 19, 1999 - * Written using The Unicode Standard, Version 2.0. - */ - -public class CharacterBreakIterator extends BaseBreakIterator -{ - // Hangul Jamo constants from Unicode book. - private static final int LBase = 0x1100; - private static final int VBase = 0x1161; - private static final int TBase = 0x11a7; - private static final int LCount = 19; - private static final int VCount = 21; - private static final int TCount = 28; - - // Information about surrogates. - private static final int highSurrogateStart = 0xD800; - private static final int highSurrogateEnd = 0xDBFF; - private static final int lowSurrogateStart = 0xDC00; - private static final int lowSurrogateEnd = 0xDFFF; - - public Object clone () - { - return new CharacterBreakIterator (this); - } - - public CharacterBreakIterator () - { - iter = null; // FIXME? - } - - private CharacterBreakIterator (CharacterBreakIterator other) - { - iter = (CharacterIterator) other.iter.clone(); - } - - // Some methods to tell us different properties of characters. - private final boolean isL (char c) - { - return c >= LBase && c <= LBase + LCount; - } - private final boolean isV (char c) - { - return c >= VBase && c <= VBase + VCount; - } - private final boolean isT (char c) - { - return c >= TBase && c <= TBase + TCount; - } - private final boolean isLVT (char c) - { - return isL (c) || isV (c) || isT (c); - } - private final boolean isHighSurrogate (char c) - { - return c >= highSurrogateStart && c <= highSurrogateEnd; - } - private final boolean isLowSurrogate (char c) - { - return c >= lowSurrogateStart && c <= lowSurrogateEnd; - } - - public int next () - { - int end = iter.getEndIndex(); - if (iter.getIndex() == end) - return DONE; - - char c; - for (char prev = CharacterIterator.DONE; iter.getIndex() < end; prev = c) - { - c = iter.next(); - if (c == CharacterIterator.DONE) - break; - int type = Character.getType(c); - - // Break after paragraph separators. - if (type == Character.PARAGRAPH_SEPARATOR) - break; - - // Now we need some lookahead. - char ahead = iter.next(); - iter.previous(); - if (ahead == CharacterIterator.DONE) - break; - int aheadType = Character.getType(ahead); - - if (aheadType != Character.NON_SPACING_MARK - && ! isLowSurrogate (ahead) - && ! isLVT (ahead)) - break; - if (! isLVT (c) && isLVT (ahead)) - break; - if (isL (c) && ! isLVT (ahead) - && aheadType != Character.NON_SPACING_MARK) - break; - if (isV (c) && ! isV (ahead) && !isT (ahead) - && aheadType != Character.NON_SPACING_MARK) - break; - if (isT (c) && ! isT (ahead) - && aheadType != Character.NON_SPACING_MARK) - break; - - if (! isHighSurrogate (c) && isLowSurrogate (ahead)) - break; - if (isHighSurrogate (c) && ! isLowSurrogate (ahead)) - break; - if (! isHighSurrogate (prev) && isLowSurrogate (c)) - break; - } - - return iter.getIndex(); - } - - public int previous () - { - if (iter.getIndex() == iter.getBeginIndex()) - return DONE; - - int start = iter.getBeginIndex(); - while (iter.getIndex() >= iter.getBeginIndex()) - { - char c = iter.previous(); - if (c == CharacterIterator.DONE) - break; - int type = Character.getType(c); - - if (type != Character.NON_SPACING_MARK - && ! isLowSurrogate (c) - && ! isLVT (c)) - break; - - // Now we need some lookahead. - char ahead = iter.previous(); - if (ahead == CharacterIterator.DONE) - { - iter.next(); - break; - } - char ahead2 = iter.previous(); - iter.next(); - iter.next(); - if (ahead2 == CharacterIterator.DONE) - break; - int aheadType = Character.getType(ahead); - - if (aheadType == Character.PARAGRAPH_SEPARATOR) - break; - - if (isLVT (c) && ! isLVT (ahead)) - break; - if (! isLVT (c) && type != Character.NON_SPACING_MARK - && isL (ahead)) - break; - if (! isV (c) && ! isT (c) && type != Character.NON_SPACING_MARK - && isV (ahead)) - break; - if (! isT (c) && type != Character.NON_SPACING_MARK - && isT (ahead)) - break; - - if (isLowSurrogate (c) && ! isHighSurrogate (ahead)) - break; - if (! isLowSurrogate (c) && isHighSurrogate (ahead)) - break; - if (isLowSurrogate (ahead) && ! isHighSurrogate (ahead2)) - break; - } - - return iter.getIndex(); - } -} diff --git a/libjava/gnu/gcj/text/LineBreakIterator.java b/libjava/gnu/gcj/text/LineBreakIterator.java deleted file mode 100644 index 4540b7ae549..00000000000 --- a/libjava/gnu/gcj/text/LineBreakIterator.java +++ /dev/null @@ -1,168 +0,0 @@ -// Default word BreakIterator. - -/* Copyright (C) 1999 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 gnu.gcj.text; - -import java.text.BreakIterator; -import java.text.CharacterIterator; - -/** - * @author Tom Tromey - * @date March 22, 1999 - * Written using The Unicode Standard, Version 2.0. - */ - -public class LineBreakIterator extends BaseBreakIterator -{ - public Object clone () - { - return new LineBreakIterator (this); - } - - public LineBreakIterator () - { - iter = null; - } - - private LineBreakIterator (LineBreakIterator other) - { - iter = (CharacterIterator) other.iter.clone(); - } - - // Some methods to tell us different properties of characters. - private final boolean isNb (char c) - { - return (c == 0x00a0 // NO-BREAK SPACE - || c == 0x2011 // NON-BREAKING HYPHEN - || c == 0xfeff); // ZERO WITH NO-BREAK SPACE - } - private final boolean isClose (int type) - { - return (type == Character.END_PUNCTUATION - // Unicode book says "comma, period, ...", which I take to - // mean "Po" class. - || type == Character.OTHER_PUNCTUATION); - } - private final boolean isIdeo (char c) - { - return (c >= 0x3040 && c <= 0x309f // Hiragana - || c >= 0x30a0 && c <= 0x30ff // Katakana - || c >= 0x4e00 && c <= 0x9fff // Han - || c >= 0x3100 && c <= 0x312f); // Bopomofo - } - - public int next () - { - int end = iter.getEndIndex(); - if (iter.getIndex() == end) - return DONE; - - while (iter.getIndex() < end) - { - char c = iter.current(); - int type = Character.getType(c); - - char n = iter.next(); - - if (n == CharacterIterator.DONE - || type == Character.PARAGRAPH_SEPARATOR - || type == Character.LINE_SEPARATOR) - break; - - // Handle two cases where we must scan for non-spacing marks. - int start = iter.getIndex(); - if (type == Character.SPACE_SEPARATOR - || type == Character.START_PUNCTUATION - || isIdeo (c)) - { - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.NON_SPACING_MARK) - n = iter.next(); - if (n == CharacterIterator.DONE) - break; - - if (type == Character.SPACE_SEPARATOR) - { - int nt = Character.getType(n); - if (nt != Character.NON_SPACING_MARK - && nt != Character.SPACE_SEPARATOR - && ! isNb (n)) - break; - } - else if (type == Character.START_PUNCTUATION) - { - if (isIdeo (n)) - { - // Open punctuation followed by non spacing marks - // and then ideograph does not have a break in - // it. So skip all this. - start = iter.getIndex(); - } - } - else - { - // Ideograph preceded this character. - if (isClose (Character.getType(n))) - break; - } - } - iter.setIndex(start); - } - - return iter.getIndex(); - } - - public int previous () - { - int start = iter.getBeginIndex(); - if (iter.getIndex() == start) - return DONE; - - while (iter.getIndex() >= start) - { - char c = iter.previous(); - if (c == CharacterIterator.DONE) - break; - int type = Character.getType(c); - - char n = iter.previous(); - if (n == CharacterIterator.DONE) - break; - iter.next(); - - int nt = Character.getType(n); - // Break after paragraph separators. - if (nt == Character.PARAGRAPH_SEPARATOR - || nt == Character.LINE_SEPARATOR) - break; - - // Skip non-spacing marks. - int init = iter.getIndex(); - while (n != CharacterIterator.DONE && nt == Character.NON_SPACING_MARK) - { - n = iter.previous(); - nt = Character.getType(n); - } - - if (nt == Character.SPACE_SEPARATOR - && type != Character.SPACE_SEPARATOR - && type != Character.NON_SPACING_MARK - && ! isNb (c)) - break; - if (! isClose (type) && isIdeo (n)) - break; - if (isIdeo (c) && nt != Character.START_PUNCTUATION) - break; - iter.setIndex(init); - } - - return iter.getIndex(); - } -} diff --git a/libjava/gnu/gcj/text/LocaleData.java b/libjava/gnu/gcj/text/LocaleData.java deleted file mode 100644 index fc273b9c43f..00000000000 --- a/libjava/gnu/gcj/text/LocaleData.java +++ /dev/null @@ -1,25 +0,0 @@ -// Generic locale data for java.text. - -/* Copyright (C) 2001 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 gnu.gcj.text; - -import java.util.ListResourceBundle; - -public class LocaleData extends ListResourceBundle -{ - private static final Object[][] contents = - { - }; - - protected Object[][] getContents () - { - return contents; - } -} diff --git a/libjava/gnu/gcj/text/LocaleData_en.java b/libjava/gnu/gcj/text/LocaleData_en.java deleted file mode 100644 index c24c1121335..00000000000 --- a/libjava/gnu/gcj/text/LocaleData_en.java +++ /dev/null @@ -1,92 +0,0 @@ -// Generic English locale data for java.text. - -/* 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 gnu.gcj.text; - -import java.util.ListResourceBundle; - -/** - * @author Tom Tromey - * @date March 4, 1999 - */ - -public final class LocaleData_en extends ListResourceBundle -{ - // These are for DateFormatSymbols. - static final String[] ampmsDefault = {"AM", "PM" }; - static final String[] erasDefault = {"BC", "AD" }; - static final String localPatternCharsDefault = "GyMdkHmsSEDFwWahKz"; - static final String[] monthsDefault = { - "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December", "" - }; - static final String[] shortMonthsDefault = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" - }; - static final String[] shortWeekdaysDefault = { - "", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" - }; - static final String[] weekdaysDefault = { - "", "Sunday", "Monday", "Tuesday", - "Wednesday", "Thursday", "Friday", "Saturday" - }; - - private static final Object[][] contents = - { - // These are for DecimalFormatSymbols. - { "decimalSeparator", "." }, - { "digit", "#" }, - { "exponential", "E" }, - { "groupingSeparator", "," }, - { "infinity", "\u221e" }, - { "minusSign", "-" }, - { "monetarySeparator", "." }, - { "NaN", "\ufffd" }, - { "patternSeparator", ";" }, - { "percent", "%" }, - { "perMill", "\u2030" }, - { "zeroDigit", "0" }, - - // These are for NumberFormat. - { "numberFormat", "#,##0.###" }, - { "percentFormat", "#,##0%" }, - - // These are for DateFormatSymbols. - { "ampm", ampmsDefault }, - { "eras", erasDefault }, - { "datePatternChars", localPatternCharsDefault }, - { "months", monthsDefault }, - { "shortMonths", shortMonthsDefault }, - { "shortWeekdays", shortWeekdaysDefault }, - { "weekdays", weekdaysDefault }, - - // These are for DateFormat. - { "shortDateFormat", "M/d/yy" }, // Java's Y2K bug. - { "mediumDateFormat", "d-MMM-yy" }, - { "longDateFormat", "MMMM d, yyyy" }, - { "fullDateFormat", "EEEE MMMM d, yyyy G" }, - { "shortTimeFormat", "h:mm a" }, - { "mediumTimeFormat", "h:mm:ss a" }, - { "longTimeFormat", "h:mm:ss a z" }, - { "fullTimeFormat", "h:mm:ss;S 'o''clock' a z" }, - - // For RuleBasedCollator. - // FIXME: this is nowhere near complete. - // In particular we must mark accents as ignorable, - // and probably other things as well. - { "collatorRule", "< 0 < 1 < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < a,A < b,B < c,C < d,D < e,E < f,F < g,G < h,H < i,I < j,J < k,K < l,L < m,M < n,N < o,O < p,P < q,Q < r,R < s,S < t,T < u,U < v,V < w,W < x,X < y,Y < z,Z" } - }; - - protected Object[][] getContents () - { - return contents; - } -} diff --git a/libjava/gnu/gcj/text/LocaleData_en_US.java b/libjava/gnu/gcj/text/LocaleData_en_US.java deleted file mode 100644 index eb5d4f14be1..00000000000 --- a/libjava/gnu/gcj/text/LocaleData_en_US.java +++ /dev/null @@ -1,81 +0,0 @@ -// US English locale data for java.text. - -/* Copyright (C) 1999 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 gnu.gcj.text; - -import java.util.ListResourceBundle; - -/** - * @author Tom Tromey - * @date March 4, 1999 - */ - -public final class LocaleData_en_US extends ListResourceBundle -{ - // These are for DateFormatSymbols. - static String[][] zoneStringsDefault = { - { "GMT", "Greenwich Mean Time", "GMT", - /**/ "Greenwich Mean Time", "GMT", "GMT" }, - { "PST", "Pacific Standard Time", "PST", - /**/ "Pacific Daylight Time", "PDT", "San Francisco" }, - { "MST", "Mountain Standard Time", "MST", - /**/ "Mountain Daylight Time", "MDT", "Denver" }, - { "PNT", "Mountain Standard Time", "MST", - /**/ "Mountain Standard Time", "MST", "Phoenix" }, - { "CST", "Central Standard Time", "CST", - /**/ "Central Daylight Time", "CDT", "Chicago" }, - { "EST", "Eastern Standard Time", "EST", - /**/ "Eastern Daylight Time", "EDT", "Boston" }, - { "IET", "Eastern Standard Time", "EST", - /**/ "Eastern Standard Time", "EST", "Indianapolis" }, - { "PRT", "Atlantic Standard Time", "AST", - /**/ "Atlantic Daylight Time", "ADT", "Halifax" }, - { "CNT", "Newfoundland Standard Time", "NST", - /**/ "Newfoundland Daylight Time", "NDT", "St. Johns" }, - { "ECT", "Central European Standard Time", "CET", - /**/ "Central European Daylight Time", "CEST", "Paris" }, - { "CTT", "China Standard Time", "CST", - /**/ "China Standard Time", "CST", "Shanghai" }, - { "JST", "Japan Standard Time", "JST", - /**/ "Japan Standard Time", "JST", "Tokyo" }, - { "HST", "Hawaii Standard Time", "HST", - /**/ "Hawaii Standard Time", "HST", "Honolulu" }, - { "AST", "Alaska Standard Time", "AKST", - /**/ "Alaska Daylight Time", "AKDT", "Anchorage" } - }; - - private static final Object[][] contents = - { - // These are for DecimalFormatSymbols. - { "currency", "$" }, - { "intlCurrencySymbol", "$" }, // FIXME? - - // These are for NumberFormat. - { "currencyFormat", "$#,##0.00;($#,##0.00)" }, - - // These are for DateFormatSymbols. - { "zoneStrings", zoneStringsDefault }, - - // These are for DateFormat. - { "shortDateFormat", "M/d/yy" }, // Java's Y2K bug. - { "mediumDateFormat", "d-MMM-yy" }, - { "longDateFormat", "MMMM d, yyyy" }, - { "fullDateFormat", "EEEE MMMM d, yyyy G" }, - { "shortTimeFormat", "h:mm a" }, - { "mediumTimeFormat", "h:mm:ss a" }, - { "longTimeFormat", "h:mm:ss a z" }, - { "fullTimeFormat", "h:mm:ss;S 'o''clock' a z" } - }; - - protected Object[][] getContents () - { - return contents; - } -} diff --git a/libjava/gnu/gcj/text/SentenceBreakIterator.java b/libjava/gnu/gcj/text/SentenceBreakIterator.java deleted file mode 100644 index af2ccf10b93..00000000000 --- a/libjava/gnu/gcj/text/SentenceBreakIterator.java +++ /dev/null @@ -1,226 +0,0 @@ -// Default sentence BreakIterator. - -/* Copyright (C) 1999 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 gnu.gcj.text; - -import java.text.BreakIterator; -import java.text.CharacterIterator; - -/** - * @author Tom Tromey - * @date March 23, 1999 - * Written using The Unicode Standard, Version 2.0. - */ - -public class SentenceBreakIterator extends BaseBreakIterator -{ - public Object clone () - { - return new SentenceBreakIterator (this); - } - - public SentenceBreakIterator () - { - iter = null; - } - - private SentenceBreakIterator (SentenceBreakIterator other) - { - iter = (CharacterIterator) other.iter.clone(); - } - - public int next () - { - int end = iter.getEndIndex(); - if (iter.getIndex() == end) - return DONE; - - while (iter.getIndex() < end) - { - char c = iter.current(); - if (c == CharacterIterator.DONE) - break; - int type = Character.getType(c); - - char n = iter.next(); - if (n == CharacterIterator.DONE) - break; - - // Always break after paragraph separator. - if (type == Character.PARAGRAPH_SEPARATOR) - break; - - if (c == '!' || c == '?') - { - // Skip close punctuation. - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.END_PUNCTUATION) - n = iter.next(); - // Skip spaces. - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.SPACE_SEPARATOR) - n = iter.next(); - // Skip optional paragraph separator. - if (n != CharacterIterator.DONE - && Character.getType(n) == Character.PARAGRAPH_SEPARATOR) - n = iter.next(); - - // There's always a break somewhere after `!' or `?'. - break; - } - - if (c == '.') - { - int save = iter.getIndex(); - // Skip close punctuation. - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.END_PUNCTUATION) - n = iter.next(); - // Skip spaces. We keep count because we need at least - // one for this period to represent a terminator. - int spcount = 0; - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.SPACE_SEPARATOR) - { - n = iter.next(); - ++spcount; - } - if (spcount > 0) - { - int save2 = iter.getIndex(); - // Skip over open puncutation. - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.START_PUNCTUATION) - n = iter.next(); - // Next character must not be lower case. - if (n == CharacterIterator.DONE - || ! Character.isLowerCase(n)) - { - iter.setIndex(save2); - break; - } - } - iter.setIndex(save); - } - } - - return iter.getIndex(); - } - - private final int previous_internal () - { - int start = iter.getBeginIndex(); - if (iter.getIndex() == start) - return DONE; - - while (iter.getIndex() >= start) - { - char c = iter.previous(); - if (c == CharacterIterator.DONE) - break; - - char n = iter.previous(); - if (n == CharacterIterator.DONE) - break; - iter.next(); - int nt = Character.getType(n); - - if (! Character.isLowerCase(c) - && (nt == Character.START_PUNCTUATION - || nt == Character.SPACE_SEPARATOR)) - { - int save = iter.getIndex(); - int save_nt = nt; - char save_n = n; - // Skip open punctuation. - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.START_PUNCTUATION) - n = iter.previous(); - if (n == CharacterIterator.DONE) - break; - if (Character.getType(n) == Character.SPACE_SEPARATOR) - { - // Must have at least once space after the `.'. - int save2 = iter.getIndex(); - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.SPACE_SEPARATOR) - n = iter.previous(); - // Skip close punctuation. - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.END_PUNCTUATION) - n = iter.previous(); - if (n == CharacterIterator.DONE || n == '.') - { - // Communicate location of actual end. - period = iter.getIndex(); - iter.setIndex(save2); - break; - } - } - iter.setIndex(save); - nt = save_nt; - n = save_n; - } - - if (nt == Character.PARAGRAPH_SEPARATOR) - { - // Communicate location of actual end. - period = iter.getIndex(); - break; - } - else if (nt == Character.SPACE_SEPARATOR - || nt == Character.END_PUNCTUATION) - { - int save = iter.getIndex(); - // Skip spaces. - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.SPACE_SEPARATOR) - n = iter.previous(); - // Skip close punctuation. - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.END_PUNCTUATION) - n = iter.previous(); - int here = iter.getIndex(); - iter.setIndex(save); - if (n == CharacterIterator.DONE || n == '!' || n == '?') - { - // Communicate location of actual end. - period = here; - break; - } - } - else if (n == '!' || n == '?') - { - // Communicate location of actual end. - period = iter.getIndex(); - break; - } - } - - return iter.getIndex(); - } - - public int previous () - { - // We want to skip over the first sentence end to the second one. - // However, at the end of the string we want the first end. - int here = iter.getIndex(); - period = here; - int first = previous_internal (); - if (here == iter.getEndIndex() || first == DONE) - return first; - iter.setIndex(period); - return previous_internal (); - } - - // This is used for communication between previous and - // previous_internal. - private int period; -} diff --git a/libjava/gnu/gcj/text/WordBreakIterator.java b/libjava/gnu/gcj/text/WordBreakIterator.java deleted file mode 100644 index 553cdefdfc1..00000000000 --- a/libjava/gnu/gcj/text/WordBreakIterator.java +++ /dev/null @@ -1,224 +0,0 @@ -// Default word BreakIterator. - -/* Copyright (C) 1999 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 gnu.gcj.text; - -import java.text.BreakIterator; -import java.text.CharacterIterator; - -/** - * @author Tom Tromey - * @date March 22, 1999 - * Written using The Unicode Standard, Version 2.0. - */ - -public class WordBreakIterator extends BaseBreakIterator -{ - public Object clone () - { - return new WordBreakIterator (this); - } - - public WordBreakIterator () - { - iter = null; - } - - private WordBreakIterator (WordBreakIterator other) - { - iter = (CharacterIterator) other.iter.clone(); - } - - // Some methods to tell us different properties of characters. - private final boolean isHira (char c) - { - return c >= 0x3040 && c <= 0x309f; - } - private final boolean isKata (char c) - { - return c >= 0x30a0 && c <= 0x30ff; - } - private final boolean isHan (char c) - { - return c >= 0x4e00 && c <= 0x9fff; - } - - public int next () - { - int end = iter.getEndIndex(); - if (iter.getIndex() == end) - return DONE; - - while (iter.getIndex() < end) - { - char c = iter.current(); - if (c == CharacterIterator.DONE) - break; - int type = Character.getType(c); - - char n = iter.next(); - if (n == CharacterIterator.DONE) - break; - - // Break after paragraph separators. - if (type == Character.PARAGRAPH_SEPARATOR - || type == Character.LINE_SEPARATOR) - break; - - // Break between letters and non-letters. - // FIXME: we treat apostrophe as part of a word. This - // is an English-ism. - boolean is_letter = Character.isLetter(c); - if (c != '\'' && ! is_letter && type != Character.NON_SPACING_MARK - && Character.isLetter(n)) - break; - - // Always break after certain symbols, such as punctuation. - // This heuristic is derived from hints in the JCL book and is - // not part of Unicode. It seems to be right, however. - // FIXME: we treat apostrophe as part of a word. This - // is an English-ism. - if (c != '\'' - && (type == Character.DASH_PUNCTUATION - || type == Character.START_PUNCTUATION - || type == Character.END_PUNCTUATION - || type == Character.CONNECTOR_PUNCTUATION - || type == Character.OTHER_PUNCTUATION - || type == Character.MATH_SYMBOL - || type == Character.CURRENCY_SYMBOL - || type == Character.MODIFIER_SYMBOL - || type == Character.OTHER_SYMBOL - || type == Character.FORMAT - || type == Character.CONTROL)) - break; - - boolean is_hira = isHira (c); - boolean is_kata = isKata (c); - boolean is_han = isHan (c); - - // Special case Japanese. - if (! is_hira && ! is_kata && ! is_han - && type != Character.NON_SPACING_MARK - && (isHira (n) || isKata (n) || isHan (n))) - break; - - if (is_hira || is_kata || is_han || is_letter) - { - // Now we need to do some lookahead. We might need to do - // quite a bit of lookahead, so we save our position and - // restore it later. - int save = iter.getIndex(); - // Skip string of non spacing marks. - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.NON_SPACING_MARK) - n = iter.next(); - if (n == CharacterIterator.DONE) - break; - if ((is_hira && ! isHira (n)) - || (is_kata && ! isHira (n) && ! isKata (n)) - || (is_han && ! isHira (n) && ! isHan (n)) - // FIXME: we treat apostrophe as part of a word. This - // is an English-ism. - || (is_letter && ! Character.isLetter(n) && n != '\'')) - break; - iter.setIndex(save); - } - } - - return iter.getIndex(); - } - - public int previous () - { - int start = iter.getBeginIndex(); - if (iter.getIndex() == start) - return DONE; - - while (iter.getIndex() >= start) - { - char c = iter.previous(); - if (c == CharacterIterator.DONE) - break; - - boolean is_hira = isHira (c); - boolean is_kata = isKata (c); - boolean is_han = isHan (c); - boolean is_letter = Character.isLetter(c); - - char n = iter.previous(); - if (n == CharacterIterator.DONE) - break; - iter.next(); - int type = Character.getType(n); - // Break after paragraph separators. - if (type == Character.PARAGRAPH_SEPARATOR - || type == Character.LINE_SEPARATOR) - break; - - // Break between letters and non-letters. - // FIXME: we treat apostrophe as part of a word. This - // is an English-ism. - if (n != '\'' && ! Character.isLetter(n) - && type != Character.NON_SPACING_MARK - && is_letter) - break; - - // Always break after certain symbols, such as punctuation. - // This heuristic is derived from hints in the JCL book and is - // not part of Unicode. It seems to be right, however. - // FIXME: we treat apostrophe as part of a word. This - // is an English-ism. - if (n != '\'' - && (type == Character.DASH_PUNCTUATION - || type == Character.START_PUNCTUATION - || type == Character.END_PUNCTUATION - || type == Character.CONNECTOR_PUNCTUATION - || type == Character.OTHER_PUNCTUATION - || type == Character.MATH_SYMBOL - || type == Character.CURRENCY_SYMBOL - || type == Character.MODIFIER_SYMBOL - || type == Character.OTHER_SYMBOL - || type == Character.FORMAT - || type == Character.CONTROL)) - break; - - // Special case Japanese. - if ((is_hira || is_kata || is_han) - && ! isHira (n) && ! isKata (n) && ! isHan (n) - && type != Character.NON_SPACING_MARK) - break; - - // We might have to skip over non spacing marks to see what's - // on the other side. - if (! is_hira || (! is_letter && c != '\'')) - { - int save = iter.getIndex(); - while (n != CharacterIterator.DONE - && Character.getType(n) == Character.NON_SPACING_MARK) - n = iter.previous(); - iter.setIndex(save); - // This is a strange case: a bunch of non-spacing marks at - // the beginning. We treat the current location as a word - // break. - if (n == CharacterIterator.DONE) - break; - if ((isHira (n) && ! is_hira) - || (isKata (n) && ! is_hira && ! is_kata) - || (isHan (n) && ! is_hira && ! is_han) - // FIXME: we treat apostrophe as part of a word. This - // is an English-ism. - || (! is_letter && c != '\'' && Character.isLetter(n))) - break; - } - } - - return iter.getIndex(); - } -} diff --git a/libjava/gnu/java/locale/LocaleInformation_de.java b/libjava/gnu/java/locale/LocaleInformation_de.java index 5eea9057cf4..208f2c50b1b 100644 --- a/libjava/gnu/java/locale/LocaleInformation_de.java +++ b/libjava/gnu/java/locale/LocaleInformation_de.java @@ -1,5 +1,5 @@ /* LocaleInformation_de.java -- German locale data - Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -47,7 +47,7 @@ public class LocaleInformation_de extends ListResourceBundle * proper format. */ private static final String collation_rules = - "-<0,1<2<3<4<5<6<7<8<9 - * This is the same list as used in the English local - */ -private static final String[] word_breaks = { " ", "\t", "\r\n", "\n" }; - -/** - * This is the list of sentence break sequences used by - * java.text.BreakIterator - *

- * This is the same list as used in the English local - */ -private static final String[] sentence_breaks = { ". " }; - -/** - * This is the list of potential line break locations. - *

- * This is the same list as used in the English local - */ -private static final String[] line_breaks = { "\t", "-", "\r\n", - "\n", ". ", ". ", ".", "? ", "? ", "?", "! ", "! ", "!", ", ", " " }; - /** * This is the list of months, fully spelled out */ @@ -281,10 +251,6 @@ private static final Object[][] contents = { // For RuleBasedCollator { "collation_rules", collation_rules }, - // For BreakIterator - { "word_breaks", word_breaks }, - { "sentence_breaks", sentence_breaks }, - { "line_breaks", line_breaks }, // For SimpleDateFormat/DateFormatSymbols { "months", months }, { "shortMonths", shortMonths }, diff --git a/libjava/gnu/java/text/BaseBreakIterator.java b/libjava/gnu/java/text/BaseBreakIterator.java new file mode 100644 index 00000000000..3220253075d --- /dev/null +++ b/libjava/gnu/java/text/BaseBreakIterator.java @@ -0,0 +1,101 @@ +/* BaseBreakIterator.java -- Base class for default BreakIterators + Copyright (C) 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package gnu.java.text; + +import java.text.BreakIterator; +import java.text.CharacterIterator; + +/** + * @author Tom Tromey + * @date March 22, 1999 + */ + +public abstract class BaseBreakIterator extends BreakIterator +{ + public int current () + { + return iter.getIndex(); + } + + public int first () + { + iter.first(); + return iter.getBeginIndex(); + } + + public int following (int pos) + { + int save = iter.getIndex(); + iter.setIndex(pos); + int r = next (); + iter.setIndex(save); + return r; + } + + public CharacterIterator getText () + { + return iter; + } + + public int last () + { + iter.last(); + // Go past the last character. + iter.next(); + return iter.getEndIndex(); + } + + public int next (int n) + { + int r = iter.getIndex (); + if (n > 0) + { + while (n > 0 && r != DONE) + { + r = next (); + --n; + } + } + else if (n < 0) + { + while (n < 0 && r != DONE) + { + r = previous (); + ++n; + } + } + return r; + } + + public void setText (CharacterIterator newText) + { + iter = newText; + } + + protected CharacterIterator iter; +} diff --git a/libjava/gnu/java/text/CharacterBreakIterator.java b/libjava/gnu/java/text/CharacterBreakIterator.java new file mode 100644 index 00000000000..68207ced873 --- /dev/null +++ b/libjava/gnu/java/text/CharacterBreakIterator.java @@ -0,0 +1,205 @@ +/* CharacterBreakIterator.java - Default character BreakIterator. + Copyright (C) 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package gnu.java.text; + +import java.text.BreakIterator; +import java.text.CharacterIterator; + +/** + * @author Tom Tromey + * @date March 19, 1999 + * Written using The Unicode Standard, Version 2.0. + */ + +public class CharacterBreakIterator extends BaseBreakIterator +{ + // Hangul Jamo constants from Unicode book. + private static final int LBase = 0x1100; + private static final int VBase = 0x1161; + private static final int TBase = 0x11a7; + private static final int LCount = 19; + private static final int VCount = 21; + private static final int TCount = 28; + + // Information about surrogates. + private static final int highSurrogateStart = 0xD800; + private static final int highSurrogateEnd = 0xDBFF; + private static final int lowSurrogateStart = 0xDC00; + private static final int lowSurrogateEnd = 0xDFFF; + + public Object clone () + { + return new CharacterBreakIterator (this); + } + + public CharacterBreakIterator () + { + iter = null; // FIXME? + } + + private CharacterBreakIterator (CharacterBreakIterator other) + { + iter = (CharacterIterator) other.iter.clone(); + } + + // Some methods to tell us different properties of characters. + private final boolean isL (char c) + { + return c >= LBase && c <= LBase + LCount; + } + private final boolean isV (char c) + { + return c >= VBase && c <= VBase + VCount; + } + private final boolean isT (char c) + { + return c >= TBase && c <= TBase + TCount; + } + private final boolean isLVT (char c) + { + return isL (c) || isV (c) || isT (c); + } + private final boolean isHighSurrogate (char c) + { + return c >= highSurrogateStart && c <= highSurrogateEnd; + } + private final boolean isLowSurrogate (char c) + { + return c >= lowSurrogateStart && c <= lowSurrogateEnd; + } + + public int next () + { + int end = iter.getEndIndex(); + if (iter.getIndex() == end) + return DONE; + + char c; + for (char prev = CharacterIterator.DONE; iter.getIndex() < end; prev = c) + { + c = iter.next(); + if (c == CharacterIterator.DONE) + break; + int type = Character.getType(c); + + // Break after paragraph separators. + if (type == Character.PARAGRAPH_SEPARATOR) + break; + + // Now we need some lookahead. + char ahead = iter.next(); + iter.previous(); + if (ahead == CharacterIterator.DONE) + break; + int aheadType = Character.getType(ahead); + + if (aheadType != Character.NON_SPACING_MARK + && ! isLowSurrogate (ahead) + && ! isLVT (ahead)) + break; + if (! isLVT (c) && isLVT (ahead)) + break; + if (isL (c) && ! isLVT (ahead) + && aheadType != Character.NON_SPACING_MARK) + break; + if (isV (c) && ! isV (ahead) && !isT (ahead) + && aheadType != Character.NON_SPACING_MARK) + break; + if (isT (c) && ! isT (ahead) + && aheadType != Character.NON_SPACING_MARK) + break; + + if (! isHighSurrogate (c) && isLowSurrogate (ahead)) + break; + if (isHighSurrogate (c) && ! isLowSurrogate (ahead)) + break; + if (! isHighSurrogate (prev) && isLowSurrogate (c)) + break; + } + + return iter.getIndex(); + } + + public int previous () + { + if (iter.getIndex() == iter.getBeginIndex()) + return DONE; + + int start = iter.getBeginIndex(); + while (iter.getIndex() >= iter.getBeginIndex()) + { + char c = iter.previous(); + if (c == CharacterIterator.DONE) + break; + int type = Character.getType(c); + + if (type != Character.NON_SPACING_MARK + && ! isLowSurrogate (c) + && ! isLVT (c)) + break; + + // Now we need some lookahead. + char ahead = iter.previous(); + if (ahead == CharacterIterator.DONE) + { + iter.next(); + break; + } + char ahead2 = iter.previous(); + iter.next(); + iter.next(); + if (ahead2 == CharacterIterator.DONE) + break; + int aheadType = Character.getType(ahead); + + if (aheadType == Character.PARAGRAPH_SEPARATOR) + break; + + if (isLVT (c) && ! isLVT (ahead)) + break; + if (! isLVT (c) && type != Character.NON_SPACING_MARK + && isL (ahead)) + break; + if (! isV (c) && ! isT (c) && type != Character.NON_SPACING_MARK + && isV (ahead)) + break; + if (! isT (c) && type != Character.NON_SPACING_MARK + && isT (ahead)) + break; + + if (isLowSurrogate (c) && ! isHighSurrogate (ahead)) + break; + if (! isLowSurrogate (c) && isHighSurrogate (ahead)) + break; + if (isLowSurrogate (ahead) && ! isHighSurrogate (ahead2)) + break; + } + + return iter.getIndex(); + } +} diff --git a/libjava/gnu/java/text/LineBreakIterator.java b/libjava/gnu/java/text/LineBreakIterator.java new file mode 100644 index 00000000000..14c1b70e4cb --- /dev/null +++ b/libjava/gnu/java/text/LineBreakIterator.java @@ -0,0 +1,185 @@ +/* LineBreakIterator.java - Default word BreakIterator. + Copyright (C) 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package gnu.java.text; + +import java.text.BreakIterator; +import java.text.CharacterIterator; + +/** + * @author Tom Tromey + * @date March 22, 1999 + * Written using The Unicode Standard, Version 2.0. + */ + +public class LineBreakIterator extends BaseBreakIterator +{ + public Object clone () + { + return new LineBreakIterator (this); + } + + public LineBreakIterator () + { + iter = null; + } + + private LineBreakIterator (LineBreakIterator other) + { + iter = (CharacterIterator) other.iter.clone(); + } + + // Some methods to tell us different properties of characters. + private final boolean isNb (char c) + { + return (c == 0x00a0 // NO-BREAK SPACE + || c == 0x2011 // NON-BREAKING HYPHEN + || c == 0xfeff); // ZERO WITH NO-BREAK SPACE + } + private final boolean isClose (int type) + { + return (type == Character.END_PUNCTUATION + // Unicode book says "comma, period, ...", which I take to + // mean "Po" class. + || type == Character.OTHER_PUNCTUATION); + } + private final boolean isIdeo (char c) + { + return (c >= 0x3040 && c <= 0x309f // Hiragana + || c >= 0x30a0 && c <= 0x30ff // Katakana + || c >= 0x4e00 && c <= 0x9fff // Han + || c >= 0x3100 && c <= 0x312f); // Bopomofo + } + + public int next () + { + int end = iter.getEndIndex(); + if (iter.getIndex() == end) + return DONE; + + while (iter.getIndex() < end) + { + char c = iter.current(); + int type = Character.getType(c); + + char n = iter.next(); + + if (n == CharacterIterator.DONE + || type == Character.PARAGRAPH_SEPARATOR + || type == Character.LINE_SEPARATOR) + break; + + // Handle two cases where we must scan for non-spacing marks. + int start = iter.getIndex(); + if (type == Character.SPACE_SEPARATOR + || type == Character.START_PUNCTUATION + || isIdeo (c)) + { + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.NON_SPACING_MARK) + n = iter.next(); + if (n == CharacterIterator.DONE) + break; + + if (type == Character.SPACE_SEPARATOR) + { + int nt = Character.getType(n); + if (nt != Character.NON_SPACING_MARK + && nt != Character.SPACE_SEPARATOR + && ! isNb (n)) + break; + } + else if (type == Character.START_PUNCTUATION) + { + if (isIdeo (n)) + { + // Open punctuation followed by non spacing marks + // and then ideograph does not have a break in + // it. So skip all this. + start = iter.getIndex(); + } + } + else + { + // Ideograph preceded this character. + if (isClose (Character.getType(n))) + break; + } + } + iter.setIndex(start); + } + + return iter.getIndex(); + } + + public int previous () + { + int start = iter.getBeginIndex(); + if (iter.getIndex() == start) + return DONE; + + while (iter.getIndex() >= start) + { + char c = iter.previous(); + if (c == CharacterIterator.DONE) + break; + int type = Character.getType(c); + + char n = iter.previous(); + if (n == CharacterIterator.DONE) + break; + iter.next(); + + int nt = Character.getType(n); + // Break after paragraph separators. + if (nt == Character.PARAGRAPH_SEPARATOR + || nt == Character.LINE_SEPARATOR) + break; + + // Skip non-spacing marks. + int init = iter.getIndex(); + while (n != CharacterIterator.DONE && nt == Character.NON_SPACING_MARK) + { + n = iter.previous(); + nt = Character.getType(n); + } + + if (nt == Character.SPACE_SEPARATOR + && type != Character.SPACE_SEPARATOR + && type != Character.NON_SPACING_MARK + && ! isNb (c)) + break; + if (! isClose (type) && isIdeo (n)) + break; + if (isIdeo (c) && nt != Character.START_PUNCTUATION) + break; + iter.setIndex(init); + } + + return iter.getIndex(); + } +} diff --git a/libjava/gnu/java/text/SentenceBreakIterator.java b/libjava/gnu/java/text/SentenceBreakIterator.java new file mode 100644 index 00000000000..9f9e81608ec --- /dev/null +++ b/libjava/gnu/java/text/SentenceBreakIterator.java @@ -0,0 +1,243 @@ +/* SentenceBreakIterator.java - Default sentence BreakIterator. + Copyright (C) 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package gnu.java.text; + +import java.text.BreakIterator; +import java.text.CharacterIterator; + +/** + * @author Tom Tromey + * @date March 23, 1999 + * Written using The Unicode Standard, Version 2.0. + */ + +public class SentenceBreakIterator extends BaseBreakIterator +{ + public Object clone () + { + return new SentenceBreakIterator (this); + } + + public SentenceBreakIterator () + { + iter = null; + } + + private SentenceBreakIterator (SentenceBreakIterator other) + { + iter = (CharacterIterator) other.iter.clone(); + } + + public int next () + { + int end = iter.getEndIndex(); + if (iter.getIndex() == end) + return DONE; + + while (iter.getIndex() < end) + { + char c = iter.current(); + if (c == CharacterIterator.DONE) + break; + int type = Character.getType(c); + + char n = iter.next(); + if (n == CharacterIterator.DONE) + break; + + // Always break after paragraph separator. + if (type == Character.PARAGRAPH_SEPARATOR) + break; + + if (c == '!' || c == '?') + { + // Skip close punctuation. + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.END_PUNCTUATION) + n = iter.next(); + // Skip spaces. + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.SPACE_SEPARATOR) + n = iter.next(); + // Skip optional paragraph separator. + if (n != CharacterIterator.DONE + && Character.getType(n) == Character.PARAGRAPH_SEPARATOR) + n = iter.next(); + + // There's always a break somewhere after `!' or `?'. + break; + } + + if (c == '.') + { + int save = iter.getIndex(); + // Skip close punctuation. + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.END_PUNCTUATION) + n = iter.next(); + // Skip spaces. We keep count because we need at least + // one for this period to represent a terminator. + int spcount = 0; + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.SPACE_SEPARATOR) + { + n = iter.next(); + ++spcount; + } + if (spcount > 0) + { + int save2 = iter.getIndex(); + // Skip over open puncutation. + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.START_PUNCTUATION) + n = iter.next(); + // Next character must not be lower case. + if (n == CharacterIterator.DONE + || ! Character.isLowerCase(n)) + { + iter.setIndex(save2); + break; + } + } + iter.setIndex(save); + } + } + + return iter.getIndex(); + } + + private final int previous_internal () + { + int start = iter.getBeginIndex(); + if (iter.getIndex() == start) + return DONE; + + while (iter.getIndex() >= start) + { + char c = iter.previous(); + if (c == CharacterIterator.DONE) + break; + + char n = iter.previous(); + if (n == CharacterIterator.DONE) + break; + iter.next(); + int nt = Character.getType(n); + + if (! Character.isLowerCase(c) + && (nt == Character.START_PUNCTUATION + || nt == Character.SPACE_SEPARATOR)) + { + int save = iter.getIndex(); + int save_nt = nt; + char save_n = n; + // Skip open punctuation. + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.START_PUNCTUATION) + n = iter.previous(); + if (n == CharacterIterator.DONE) + break; + if (Character.getType(n) == Character.SPACE_SEPARATOR) + { + // Must have at least once space after the `.'. + int save2 = iter.getIndex(); + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.SPACE_SEPARATOR) + n = iter.previous(); + // Skip close punctuation. + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.END_PUNCTUATION) + n = iter.previous(); + if (n == CharacterIterator.DONE || n == '.') + { + // Communicate location of actual end. + period = iter.getIndex(); + iter.setIndex(save2); + break; + } + } + iter.setIndex(save); + nt = save_nt; + n = save_n; + } + + if (nt == Character.PARAGRAPH_SEPARATOR) + { + // Communicate location of actual end. + period = iter.getIndex(); + break; + } + else if (nt == Character.SPACE_SEPARATOR + || nt == Character.END_PUNCTUATION) + { + int save = iter.getIndex(); + // Skip spaces. + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.SPACE_SEPARATOR) + n = iter.previous(); + // Skip close punctuation. + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.END_PUNCTUATION) + n = iter.previous(); + int here = iter.getIndex(); + iter.setIndex(save); + if (n == CharacterIterator.DONE || n == '!' || n == '?') + { + // Communicate location of actual end. + period = here; + break; + } + } + else if (n == '!' || n == '?') + { + // Communicate location of actual end. + period = iter.getIndex(); + break; + } + } + + return iter.getIndex(); + } + + public int previous () + { + // We want to skip over the first sentence end to the second one. + // However, at the end of the string we want the first end. + int here = iter.getIndex(); + period = here; + int first = previous_internal (); + if (here == iter.getEndIndex() || first == DONE) + return first; + iter.setIndex(period); + return previous_internal (); + } + + // This is used for communication between previous and + // previous_internal. + private int period; +} diff --git a/libjava/gnu/java/text/WordBreakIterator.java b/libjava/gnu/java/text/WordBreakIterator.java new file mode 100644 index 00000000000..5cf50147b0c --- /dev/null +++ b/libjava/gnu/java/text/WordBreakIterator.java @@ -0,0 +1,241 @@ +/* WordBreakIterator.java - Default word BreakIterator. + Copyright (C) 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package gnu.java.text; + +import java.text.BreakIterator; +import java.text.CharacterIterator; + +/** + * @author Tom Tromey + * @date March 22, 1999 + * Written using The Unicode Standard, Version 2.0. + */ + +public class WordBreakIterator extends BaseBreakIterator +{ + public Object clone () + { + return new WordBreakIterator (this); + } + + public WordBreakIterator () + { + iter = null; + } + + private WordBreakIterator (WordBreakIterator other) + { + iter = (CharacterIterator) other.iter.clone(); + } + + // Some methods to tell us different properties of characters. + private final boolean isHira (char c) + { + return c >= 0x3040 && c <= 0x309f; + } + private final boolean isKata (char c) + { + return c >= 0x30a0 && c <= 0x30ff; + } + private final boolean isHan (char c) + { + return c >= 0x4e00 && c <= 0x9fff; + } + + public int next () + { + int end = iter.getEndIndex(); + if (iter.getIndex() == end) + return DONE; + + while (iter.getIndex() < end) + { + char c = iter.current(); + if (c == CharacterIterator.DONE) + break; + int type = Character.getType(c); + + char n = iter.next(); + if (n == CharacterIterator.DONE) + break; + + // Break after paragraph separators. + if (type == Character.PARAGRAPH_SEPARATOR + || type == Character.LINE_SEPARATOR) + break; + + // Break between letters and non-letters. + // FIXME: we treat apostrophe as part of a word. This + // is an English-ism. + boolean is_letter = Character.isLetter(c); + if (c != '\'' && ! is_letter && type != Character.NON_SPACING_MARK + && Character.isLetter(n)) + break; + + // Always break after certain symbols, such as punctuation. + // This heuristic is derived from hints in the JCL book and is + // not part of Unicode. It seems to be right, however. + // FIXME: we treat apostrophe as part of a word. This + // is an English-ism. + if (c != '\'' + && (type == Character.DASH_PUNCTUATION + || type == Character.START_PUNCTUATION + || type == Character.END_PUNCTUATION + || type == Character.CONNECTOR_PUNCTUATION + || type == Character.OTHER_PUNCTUATION + || type == Character.MATH_SYMBOL + || type == Character.CURRENCY_SYMBOL + || type == Character.MODIFIER_SYMBOL + || type == Character.OTHER_SYMBOL + || type == Character.FORMAT + || type == Character.CONTROL)) + break; + + boolean is_hira = isHira (c); + boolean is_kata = isKata (c); + boolean is_han = isHan (c); + + // Special case Japanese. + if (! is_hira && ! is_kata && ! is_han + && type != Character.NON_SPACING_MARK + && (isHira (n) || isKata (n) || isHan (n))) + break; + + if (is_hira || is_kata || is_han || is_letter) + { + // Now we need to do some lookahead. We might need to do + // quite a bit of lookahead, so we save our position and + // restore it later. + int save = iter.getIndex(); + // Skip string of non spacing marks. + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.NON_SPACING_MARK) + n = iter.next(); + if (n == CharacterIterator.DONE) + break; + if ((is_hira && ! isHira (n)) + || (is_kata && ! isHira (n) && ! isKata (n)) + || (is_han && ! isHira (n) && ! isHan (n)) + // FIXME: we treat apostrophe as part of a word. This + // is an English-ism. + || (is_letter && ! Character.isLetter(n) && n != '\'')) + break; + iter.setIndex(save); + } + } + + return iter.getIndex(); + } + + public int previous () + { + int start = iter.getBeginIndex(); + if (iter.getIndex() == start) + return DONE; + + while (iter.getIndex() >= start) + { + char c = iter.previous(); + if (c == CharacterIterator.DONE) + break; + + boolean is_hira = isHira (c); + boolean is_kata = isKata (c); + boolean is_han = isHan (c); + boolean is_letter = Character.isLetter(c); + + char n = iter.previous(); + if (n == CharacterIterator.DONE) + break; + iter.next(); + int type = Character.getType(n); + // Break after paragraph separators. + if (type == Character.PARAGRAPH_SEPARATOR + || type == Character.LINE_SEPARATOR) + break; + + // Break between letters and non-letters. + // FIXME: we treat apostrophe as part of a word. This + // is an English-ism. + if (n != '\'' && ! Character.isLetter(n) + && type != Character.NON_SPACING_MARK + && is_letter) + break; + + // Always break after certain symbols, such as punctuation. + // This heuristic is derived from hints in the JCL book and is + // not part of Unicode. It seems to be right, however. + // FIXME: we treat apostrophe as part of a word. This + // is an English-ism. + if (n != '\'' + && (type == Character.DASH_PUNCTUATION + || type == Character.START_PUNCTUATION + || type == Character.END_PUNCTUATION + || type == Character.CONNECTOR_PUNCTUATION + || type == Character.OTHER_PUNCTUATION + || type == Character.MATH_SYMBOL + || type == Character.CURRENCY_SYMBOL + || type == Character.MODIFIER_SYMBOL + || type == Character.OTHER_SYMBOL + || type == Character.FORMAT + || type == Character.CONTROL)) + break; + + // Special case Japanese. + if ((is_hira || is_kata || is_han) + && ! isHira (n) && ! isKata (n) && ! isHan (n) + && type != Character.NON_SPACING_MARK) + break; + + // We might have to skip over non spacing marks to see what's + // on the other side. + if (! is_hira || (! is_letter && c != '\'')) + { + int save = iter.getIndex(); + while (n != CharacterIterator.DONE + && Character.getType(n) == Character.NON_SPACING_MARK) + n = iter.previous(); + iter.setIndex(save); + // This is a strange case: a bunch of non-spacing marks at + // the beginning. We treat the current location as a word + // break. + if (n == CharacterIterator.DONE) + break; + if ((isHira (n) && ! is_hira) + || (isKata (n) && ! is_hira && ! is_kata) + || (isHan (n) && ! is_hira && ! is_han) + // FIXME: we treat apostrophe as part of a word. This + // is an English-ism. + || (! is_letter && c != '\'' && Character.isLetter(n))) + break; + } + } + + return iter.getIndex(); + } +} diff --git a/libjava/java/text/Annotation.java b/libjava/java/text/Annotation.java new file mode 100644 index 00000000000..8e04a769fb4 --- /dev/null +++ b/libjava/java/text/Annotation.java @@ -0,0 +1,102 @@ +/* Annotation.java -- Wrapper for a text attribute object + Copyright (C) 1998, 1999 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.text; + +/** + * This class is used as a wrapper for a text attribute object. Annotation + * objects are associated with a specific range of text. Changing either + * the text range or the underlying text invalidates the object. + * + * @version 0.0 + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class Annotation +{ + +/* + * Instance Variables + */ + +/** + * This is the attribute object being wrappered + */ +private Object attrib; + +/*************************************************************************/ + +/** + * Constructors + */ + +/** + * This method initializes a new instance of Annotation to + * wrapper the specified text attribute object. + * + * @param attrib The text attribute Object to wrapper. + */ +public +Annotation(Object attrib) +{ + this.attrib = attrib; +} + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * This method returns the text attribute object this Annotation + * instance is wrappering. + * + * @return The text attribute object for this Annotation. + */ +public Object +getValue() +{ + return(attrib); +} + +/*************************************************************************/ + +/** + * This method returns a String representation of this + * object. + * + * @return This object as a String. + */ +public String +toString() +{ + return(getClass().getName() + "[value=" + attrib.toString() + "]"); +} + +} // class Annotation + diff --git a/libjava/java/text/AttributedCharacterIterator.java b/libjava/java/text/AttributedCharacterIterator.java new file mode 100644 index 00000000000..379181e7c09 --- /dev/null +++ b/libjava/java/text/AttributedCharacterIterator.java @@ -0,0 +1,333 @@ +/* AttributedCharacterIterator.java -- Iterate over attributes + Copyright (C) 1998, 1999 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.text; + +import java.io.Serializable; +import java.io.InvalidObjectException; +import java.util.Set; +import java.util.Map; + +/** + * This interface extends the CharacterIterator interface + * in order to support iteration over character attributes as well as + * over the characters themselves. + *

+ * In addition to attributes of specific characters, this interface + * supports the concept of the "attribute run", which is an attribute + * that is defined for a particular value across an entire range of + * characters or which is undefined over a range of characters. + * + * @version 0.0 + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public interface AttributedCharacterIterator extends CharacterIterator +{ + +/* + * Inner Classes + */ + +/** + * This class defines attribute keys that are used as text attributes. + */ +public static class Attribute implements Serializable +{ + +/*************************************************************************/ + +/* + * Static Variables + */ + +/** + * This is the attribute for the language of the text. The value of + * attributes of this key type are instances of Locale. + */ +public static final Attribute LANGUAGE = new Attribute("LANGUAGE"); + +/** + * This is the attribute for the reading form of text. This is used + * for storing pronunciation along with the written text for languages + * which need it. The value of attributes of this key type are + * instances of Annotation which wrappers a String. + */ +public static final Attribute READING = new Attribute("READING"); + +/** + * This is the attribute for input method segments. The value of attributes + * of this key type are instances of Annotation which wrapper + * a String. + */ +public static final Attribute INPUT_METHOD_SEGMENT = + new Attribute("INPUT_METHOD_SEGMENT"); + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * This is the name of the attribute key + * @serial + */ +private String name; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * This method initializes a new instance of this class with the specified + * name. + * + * @param name The name of this attribute key. + */ +protected +Attribute(String name) +{ + this.name = name; +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * This method returns the name of this attribute. + * + * @return The attribute name + */ +protected String +getName() +{ + return(name); +} + +/*************************************************************************/ + +/** + * This method resolves an instance of AttributedCharacterIterator.Attribute + * that is being deserialized to one of the three pre-defined attribute + * constants. It does this by comparing the names of the attributes. The + * constant that the deserialized object resolves to is returned. + * + * @return The resolved contant value + * + * @exception InvalidObjectException If the object being deserialized cannot be resolved. + */ +protected Object +readResolve() throws InvalidObjectException +{ + if (this.equals(READING)) + return(READING); + + if (this.equals(LANGUAGE)) + return(LANGUAGE); + + if (this.equals(INPUT_METHOD_SEGMENT)) + return(INPUT_METHOD_SEGMENT); + + throw new InvalidObjectException("Can't resolve Attribute: " + getName()); +} + +/*************************************************************************/ + +/** + * This method tests this object for equality against the specified object. + * The two objects will be considered equal if and only if: + *

    + *
  • The specified object is not null. + *
  • The specified object is an instance of AttributedCharacterIterator.Attribute. + *
  • The specified object has the same attribute name as this object. + *
+ * + * @param The Object to test for equality against this object. + * + * @return true if the specified object is equal to this one, false otherwise. + */ +public final boolean +equals(Object obj) +{ + if (obj == this) + return(true); + else + return(false); +} + +/*************************************************************************/ + +/** + * This method returns a hash value for this object. + * + * @return A hash value for this object. + */ +public final int +hashCode() +{ + return(super.hashCode()); +} + +/*************************************************************************/ + +/** + * This method returns a String representation of this object. + * + * @return A String representation of this object. + */ +public String +toString() +{ + return(getClass().getName() + "(" + getName() + ")"); +} + +} // Inner class Attribute + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * This method returns a list of all keys that are defined for the + * text range. This can be an empty list if no attributes are defined. + * + * @return A list of keys + */ +public abstract Set +getAllAttributeKeys(); + +/*************************************************************************/ + +/** + * This method returns a Map of the attributed defined for + * the current character. + * + * @return A Map of the attributes for the current character. + */ +public abstract Map +getAttributes(); + +/*************************************************************************/ + +/** + * This method returns the value of the specified attribute for the + * current character. If the attribute is not defined for the current + * character, null is returned. + * + * @param attrib The attribute to retrieve the value of. + * + * @return The value of the specified attribute + */ +public abstract Object +getAttribute(AttributedCharacterIterator.Attribute attrib); + +/*************************************************************************/ + +/** + * This method returns the index of the first character in the run that + * contains all attributes defined for the current character. + * + * @return The start index of the run + */ +public abstract int +getRunStart(); + +/*************************************************************************/ + +/** + * This method returns the index of the first character in the run that + * contains all attributes in the specified Set defined for + * the current character. + * + * @param attribs The Set of attributes. + * + * @return The start index of the run. + */ +public abstract int +getRunStart(Set attribs); + +/*************************************************************************/ + +/** + * This method returns the index of the first character in the run that + * contains the specified attribute defined for the current character. + * + * @param attrib The attribute. + * + * @return The start index of the run. + */ +public abstract int +getRunStart(AttributedCharacterIterator.Attribute attrib); + +/*************************************************************************/ + +/** + * This method returns the index of the character after the end of the run + * that contains all attributed defined for the current character. + * + * @return The end index of the run. + */ +public abstract int +getRunLimit(); + +/*************************************************************************/ + +/** + * This method returns the index of the character after the end of the run + * that contains all attributes in the specified Set defined + * for the current character. + * + * @param attribs The Set of attributes. + * + * @return The end index of the run. + */ +public abstract int +getRunLimit(Set attribs); + +/*************************************************************************/ + +/** + * This methods returns the index of the character after the end of the run + * that contains the specified attribute defined for the current character. + * + * @param attrib The attribute. + * + * @return The end index of the run. + */ +public abstract int +getRunLimit(AttributedCharacterIterator.Attribute attrib); + +} // interface AttributedCharacterIterator + diff --git a/libjava/java/text/AttributedString.java b/libjava/java/text/AttributedString.java new file mode 100644 index 00000000000..cc664dece78 --- /dev/null +++ b/libjava/java/text/AttributedString.java @@ -0,0 +1,431 @@ +/* AttributedString.java -- Models text with attributes + Copyright (C) 1998, 1999 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.text; + +import java.util.Iterator; +import java.util.Hashtable; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * This class models a String with attributes over various + * subranges of the string. It allows applications to access this + * information via the AttributedCharcterIterator interface. + * + * @version 0.0 + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ +public class AttributedString +{ + +/*************************************************************************/ + +/* + * Inner Classes + */ + +/** + * This class contains the attributes and ranges of text over which + * that attributes apply. + */ +final class AttributeRange +{ + +/* + * Instance Variables + */ + +/** + * A Map of the attributes + */ +Map attribs; + +/** + * The beginning index of the attributes + */ +int begin_index; + +/** + * The ending index of the attributes + */ +int end_index; + +/*************************************************************************/ + +/* + * Constructors + */ + +AttributeRange(Map attribs, int begin_index, int end_index) +{ + this.attribs = attribs; + this.begin_index = begin_index; + this.end_index = end_index; +} + +} // Inner class AttributeRange + +/*************************************************************************/ + +/* + * Instance Variables + */ + +/** + * This object holds the string we are representing. + */ +private StringCharacterIterator sci; + +/** + * This is the attribute information + */ +private AttributeRange[] attribs; + +/*************************************************************************/ + +/* + * Constructors + */ + +/** + * This method initializes a new instance of AttributedString + * that represents the specified String with no attributes. + * + * @param str The String to be attributed. + */ +public +AttributedString(String str) +{ + sci = new StringCharacterIterator(str); + attribs = new AttributeRange[0]; +} + +/*************************************************************************/ + +/** + * This method initializes a new instance of AttributedString + * that represents that specified String with the specified + * attributes over the entire length of the String. + * + * @param str The String to be attributed. + * @param attributes The attribute list. + */ +public +AttributedString(String str, Map attributes) +{ + this(str); + + attribs = new AttributeRange[1]; + attribs[0] = new AttributeRange(attributes, 0, str.length()); +} + +/*************************************************************************/ + +/** + * This method initializes a new instance of AttributedString + * that will use the text and attribute information from the specified + * AttributedCharacterIterator. + * + * @param aci The AttributedCharacterIterator containing the text and attribute information. + */ +public +AttributedString(AttributedCharacterIterator aci) +{ + this(aci, aci.getBeginIndex(), aci.getEndIndex(), null); +} + +/*************************************************************************/ + +/** + * This method initializes a new instance of AttributedString + * that will use the text and attribute information from the specified + * subrange of the specified AttributedCharacterIterator. + * + * @param aci The AttributedCharacterIterator containing the text and attribute information. + * @param begin_index The beginning index of the text subrange. + * @param end_index The ending index of the text subrange. + */ +public +AttributedString(AttributedCharacterIterator aci, int begin_index, + int end_index) +{ + this(aci, begin_index, end_index, null); +} + +/*************************************************************************/ + +/** + * This method initializes a new instance of AttributedString + * that will use the text and attribute information from the specified + * subrange of the specified AttributedCharacterIterator. + * Only attributes from the source iterator that are present in the + * specified array of attributes will be included in the attribute list + * for this object. + * + * @param aci The AttributedCharacterIterator containing the text and attribute information. + * @param begin_index The beginning index of the text subrange. + * @param end_index The ending index of the text subrange. + * @param attributes A list of attributes to include from the iterator, or null to include all attributes. + */ +public +AttributedString(AttributedCharacterIterator aci, int begin_index, + int end_index, AttributedCharacterIterator.Attribute[] attributes) +{ + // Validate some arguments + if ((begin_index < 0) || (end_index < begin_index)) + throw new IllegalArgumentException("Bad index values"); + + StringBuffer sb = new StringBuffer(""); + + // Get the valid attribute list + Set all_attribs = aci.getAllAttributeKeys(); + if (attributes != null) + { + Set valid_attribs = new HashSet(); + Iterator iter = all_attribs.iterator(); + while (iter.hasNext()) + { + Object obj = iter.next(); + + int i; + for (i = 0; i < attributes.length; i++) + if (obj.equals(attributes[0])) + break; + + if (i == attributes.length) + continue; + + valid_attribs.add(obj); + } + + all_attribs = valid_attribs; + } + + // Loop through and extract the attributes + char c = aci.setIndex(begin_index); + + do + { + sb.append(c); + + Iterator iter = all_attribs.iterator(); + while(iter.hasNext()) + { + Object obj = iter.next(); + + // What should we do if this is not true? + if (!(obj instanceof AttributedCharacterIterator.Attribute)) + continue; + + AttributedCharacterIterator.Attribute attrib = + (AttributedCharacterIterator.Attribute)obj; + + // Make sure the attribute is defined. + int rl = aci.getRunLimit(attrib); + if (rl == -1) + continue; + if (rl > end_index) + rl = end_index; + rl -= begin_index; + + // Check to see if we already processed this one + int rs = aci.getRunStart(attrib); + if ((rs < aci.getIndex()) && (aci.getIndex() != begin_index)) + continue; + + // If the attribute run starts before the beginning index, we + // need to junk it if it is an Annotation. + Object attrib_obj = aci.getAttribute(attrib); + if (rs < begin_index) + { + if (attrib_obj instanceof Annotation) + continue; + + rs = begin_index; + } + else + { + rs -= begin_index; + } + + // Create a map object. Yes this will only contain one attribute + Map new_map = new Hashtable(); + new_map.put(attrib, attrib_obj); + + // Add it to the attribute list. Yes this is a bad way to do things. + AttributeRange[] new_list = new AttributeRange[attribs.length + 1]; + System.arraycopy(attribs, 0, new_list, 0, attribs.length); + attribs = new_list; + attribs[attribs.length - 1] = new AttributeRange(new_map, rs, rl); + } + + c = aci.next(); + } + while(c != CharacterIterator.DONE); + + sci = new StringCharacterIterator(sb.toString()); +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +/** + * This method adds a new attribute that will cover the entire string. + * + * @param attrib The attribute to add. + * @param value The value of the attribute. + */ +public void +addAttribute(AttributedCharacterIterator.Attribute attrib, Object value) +{ + addAttribute(attrib, value, 0, sci.getEndIndex() - 1); +} + +/*************************************************************************/ + +/** + * This method adds a new attribute that will cover the specified subrange + * of the string. + * + * @param attrib The attribute to add. + * @param value The value of the attribute. + * @param begin_index The beginning index of the subrange. + * @param end_index The ending index of the subrange. + * + * @exception IllegalArgumentException If attribute is null or the subrange is not valid. + */ +public void +addAttribute(AttributedCharacterIterator.Attribute attrib, Object value, + int begin_index, int end_index) +{ + if (attrib == null) + throw new IllegalArgumentException("null attribute"); + + Hashtable ht = new Hashtable(); + ht.put(attrib, value); + + addAttributes(ht, begin_index, end_index); +} + +/*************************************************************************/ + +/** + * This method adds all of the attributes in the specified list to the + * specified subrange of the string. + * + * @param attributes The list of attributes. + * @param begin_index The beginning index. + * @param end_index The ending index + * + * @param IllegalArgumentException If the list is null or the subrange is not valid. + */ +public void +addAttributes(Map attributes, int begin_index, int end_index) +{ + if (attributes == null) + throw new IllegalArgumentException("null attribute"); + + if ((begin_index < 0) || (end_index > sci.getEndIndex()) || + (end_index < begin_index)) + throw new IllegalArgumentException("bad range"); + + AttributeRange[] new_list = new AttributeRange[attribs.length + 1]; + System.arraycopy(attribs, 0, new_list, 0, attribs.length); + attribs = new_list; + attribs[attribs.length - 1] = new AttributeRange(attributes, begin_index, + end_index); +} + +/*************************************************************************/ + +/** + * This method returns an AttributedCharacterIterator that + * will iterate over the entire string. + * + * @return An AttributedCharacterIterator for the entire string. + */ +public AttributedCharacterIterator +getIterator() +{ + return(new AttributedStringIterator(sci, attribs, 0, sci.getEndIndex() - 1, + null)); +} + +/*************************************************************************/ + +/** + * This method returns an AttributedCharacterIterator that + * will iterate over the entire string. This iterator will return information + * about the list of attributes in the specified array. Attributes not in + * the array may or may not be returned by the iterator. If the specified + * array is null, all attributes will be returned. + * + * @param attributes A list of attributes to include in the returned iterator. + * + * @return An AttributedCharacterIterator for this string. + */ +public AttributedCharacterIterator +getIterator(AttributedCharacterIterator.Attribute[] attributes) +{ + return(getIterator(attributes, 0, sci.getEndIndex() - 1)); +} + +/*************************************************************************/ + +/** + * This method returns an AttributedCharacterIterator that + * will iterate over the specified subrange. This iterator will return information + * about the list of attributes in the specified array. Attributes not in + * the array may or may not be returned by the iterator. If the specified + * array is null, all attributes will be returned. + * + * @param attributes A list of attributes to include in the returned iterator. + * @param begin_index The beginning index of the subrange. + * @param end_index The ending index of the subrange. + * + * @return An AttributedCharacterIterator for this string. + */ +public AttributedCharacterIterator +getIterator(AttributedCharacterIterator.Attribute[] attributes, + int begin_index, int end_index) +{ + if ((begin_index < 0) || (end_index > sci.getEndIndex()) || + (end_index < begin_index)) + throw new IllegalArgumentException("bad range"); + + return(new AttributedStringIterator(sci, attribs, begin_index, end_index, + attributes)); +} + +} // class AttributedString + diff --git a/libjava/java/text/AttributedStringIterator.java b/libjava/java/text/AttributedStringIterator.java new file mode 100644 index 00000000000..4d0e4e66655 --- /dev/null +++ b/libjava/java/text/AttributedStringIterator.java @@ -0,0 +1,351 @@ +/* AttributedStringIterator.java -- Class to iterate over AttributedString + Copyright (C) 1998, 1999 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ + + +package java.text; + +import java.util.Set; +import java.util.HashSet; +import java.util.Map; +import java.util.HashMap; +import java.util.Iterator; + +/** + * 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 +{ + +/*************************************************************************/ + +/** + * Instance Variables + */ + +/** + * 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 AttributedCharacterIterator.Attribute[] restricts; + +/*************************************************************************/ + +/* + * Constructors + */ + +AttributedStringIterator(StringCharacterIterator sci, + AttributedString.AttributeRange[] attribs, + int begin_index, int end_index, + AttributedCharacterIterator.Attribute[] restricts) +{ + this.ci = new StringCharacterIterator(sci, begin_index, end_index); + this.attribs = attribs; + this.restricts = restricts; +} + +/*************************************************************************/ + +/* + * Instance Methods + */ + +// 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 +getAllAttributeKeys() +{ + HashSet s = new HashSet(); + if (attribs == null) + return(s); + + for (int i = 0; i < attribs.length; i++) + { + Set key_set = attribs[i].attribs.keySet(); + Iterator iter = key_set.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(getAttributes().keySet())); +} + +public int +getRunLimit(AttributedCharacterIterator.Attribute attrib) +{ + HashSet s = new HashSet(); + s.add(attrib); + + return(getRunLimit(s)); +} + +public synchronized int +getRunLimit(Set attribute_set) +{ + int orig_index = ci.getIndex(); + int run_limit; + + do + { + run_limit = ci.getIndex(); + + Map attribute_map = getAttributes(); + + boolean found = false; + Iterator iter = attribute_set.iterator(); + while(iter.hasNext()) + if (!attribute_map.containsKey(iter.next())) + { + found = true; + break; + } + + if (found) + break; + } + while (ci.next() != CharacterIterator.DONE); + + boolean hit_end = (ci.previous() == CharacterIterator.DONE); + + ci.setIndex(orig_index); + + if (run_limit == orig_index) + return(-1); // No characters match the given attributes +// else if (!hit_end) +// --run_limit; + + return(run_limit); +} + +/*************************************************************************/ + +/** + * Various methods that determine where the run begins for various + * attribute combinations. + */ + +public int +getRunStart() +{ + return(getRunStart(getAttributes().keySet())); +} + +public int +getRunStart(AttributedCharacterIterator.Attribute attrib) +{ + HashSet s = new HashSet(); + s.add(attrib); + + return(getRunStart(s)); +} + +public int +getRunStart(Set attribute_set) +{ + int orig_index = ci.getIndex(); + int run_start; + + do + { + run_start = ci.getIndex(); + + Map attribute_map = getAttributes(); + + Iterator iter = attribute_set.iterator(); + while(iter.hasNext()) + if (!attribute_map.containsKey(iter.next())) + break; + + if (iter.hasNext()) + break; + } + while (ci.previous() != CharacterIterator.DONE); + + boolean hit_beginning = (ci.previous() == CharacterIterator.DONE); + + ci.setIndex(orig_index); + + if (run_start == orig_index) + return(-1); // No characters match the given attributes + else if (!hit_beginning) + ++run_start; + + return(run_start); +} + +/*************************************************************************/ + +public Object +getAttribute(AttributedCharacterIterator.Attribute attrib) +{ + if (attribs == null) + return(null); + + for (int i = 0; i < attribs.length; i++) + { + Set key_set = attribs[i].attribs.keySet(); + Iterator iter = key_set.iterator(); + while (iter.hasNext()) + { + Object obj = iter.next(); + + // Check for attribute match and range match + if (obj.equals(attrib)) + if ((ci.getIndex() >= attribs[i].begin_index) && + (ci.getIndex() <= attribs[i].end_index)) + return(attribs[i].attribs.get(obj)); + } + } + + return(null); +} + +/*************************************************************************/ + +/** + * Return a list of all the attributes and values defined for this + * character + */ +public Map +getAttributes() +{ + HashMap m = new HashMap(); + if (attribs == null) + return(m); + + for (int i = 0; i < attribs.length; i++) + { + if ((ci.getIndex() >= attribs[i].begin_index) && + (ci.getIndex() <= attribs[i].end_index)) + m.putAll(attribs[i].attribs); + } + + return(m); +} + +} // class AttributedStringIterator + diff --git a/libjava/java/text/BreakIterator.java b/libjava/java/text/BreakIterator.java index ef971bf4f75..907e07d5130 100644 --- a/libjava/java/text/BreakIterator.java +++ b/libjava/java/text/BreakIterator.java @@ -1,12 +1,29 @@ -// BreakIterator.java - Iterate over logical breaks in text. +/* BreakIterator.java -- Breaks text into elements + Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. -/* Copyright (C) 1999 Free Software Foundation +This file is part of GNU Classpath. - This file is part of libgcj. +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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ package java.text; @@ -15,31 +32,75 @@ import java.util.MissingResourceException; import java.util.ResourceBundle; /** + * This class iterates over text elements such as words, lines, sentences, + * and characters. It can only iterate over one of these text elements at + * a time. An instance of this class configured for the desired iteration + * type is created by calling one of the static factory methods, not + * by directly calling a constructor. + * * @author Tom Tromey + * @author Aaron M. Renn (arenn@urbanophile.com) * @date March 19, 1999 */ /* Written using "Java Class Libraries", 2nd edition, plus online * API docs for JDK 1.2 beta from http://www.javasoft.com. * Status: Believed complete and correct to 1.1. */ - public abstract class BreakIterator implements Cloneable { + /** + * This value is returned by the next() and + * previous in order to indicate that the end of the + * text has been reached. + */ // The value was discovered by writing a test program. public static final int DONE = -1; + /** + * This method initializes a new instance of BreakIterator. + * This protected constructor is available to subclasses as a default + * no-arg superclass constructor. + */ protected BreakIterator () { } + /** + * This method returns the index of the current text element boundary. + * + * @return The current text boundary. + */ public abstract int current (); + + /** + * This method returns the first text element boundary in the text being + * iterated over. + * + * @return The first text boundary. + */ public abstract int first (); + + /** + * This methdod returns the offset of the text element boundary following + * the specified offset. + * + * @param offset The text index from which to find the next text boundary. + * + * @param The next text boundary following the specified index. + */ public abstract int following (int pos); + /** + * This method returns a list of locales for which instances of + * BreakIterator are available. + * + * @return A list of available locales + */ public static synchronized Locale[] getAvailableLocales () { - // FIXME. - return null; + Locale[] l = new Locale[1]; + l[0] = Locale.US; + return l; } private static BreakIterator getInstance (String type, Locale loc) @@ -48,7 +109,8 @@ public abstract class BreakIterator implements Cloneable try { ResourceBundle res - = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", loc); + = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", + loc); className = res.getString(type); } catch (MissingResourceException x) @@ -74,60 +136,135 @@ public abstract class BreakIterator implements Cloneable } } + /** + * This method returns an instance of BreakIterator that will + * iterate over characters as defined in the default locale. + * + * @return A BreakIterator instance for the default locale. + */ public static BreakIterator getCharacterInstance () { return getCharacterInstance (Locale.getDefault()); } + /** + * This method returns an instance of BreakIterator that will + * iterate over characters as defined in the specified locale. If the + * desired locale is not available, the default locale is used. + * + * @param locale The desired locale. + * + * @return A BreakIterator instance for the default locale. + */ public static BreakIterator getCharacterInstance (Locale loc) { BreakIterator r = getInstance ("CharacterIterator", loc); if (r == null) - r = new gnu.gcj.text.CharacterBreakIterator (); + r = new gnu.java.text.CharacterBreakIterator (); return r; } + /** + * This method returns an instance of BreakIterator that will + * iterate over line breaks as defined in the default locale. + * + * @return A BreakIterator instance for the default locale. + */ public static BreakIterator getLineInstance () { return getLineInstance (Locale.getDefault()); } + /** + * This method returns an instance of BreakIterator that will + * iterate over line breaks as defined in the specified locale. If the + * desired locale is not available, the default locale is used. + * + * @param locale The desired locale. + * + * @return A BreakIterator instance for the default locale. + */ public static BreakIterator getLineInstance (Locale loc) { BreakIterator r = getInstance ("LineIterator", loc); if (r == null) - r = new gnu.gcj.text.LineBreakIterator (); + r = new gnu.java.text.LineBreakIterator (); return r; } + /** + * This method returns an instance of BreakIterator that will + * iterate over sentences as defined in the default locale. + * + * @return A BreakIterator instance for the default locale. + */ public static BreakIterator getSentenceInstance () { return getSentenceInstance (Locale.getDefault()); } + /** + * This method returns an instance of BreakIterator that will + * iterate over sentences as defined in the specified locale. If the + * desired locale is not available, the default locale is used. + * + * @param locale The desired locale. + * + * @return A BreakIterator instance for the default locale. + */ public static BreakIterator getSentenceInstance (Locale loc) { BreakIterator r = getInstance ("SentenceIterator", loc); if (r == null) - r = new gnu.gcj.text.SentenceBreakIterator (); + r = new gnu.java.text.SentenceBreakIterator (); return r; } + /** + * This method returns the text this object is iterating over as a + * CharacterIterator. + * + * @param The text being iterated over. + */ public abstract CharacterIterator getText (); + /** + * This method returns an instance of BreakIterator that will + * iterate over words as defined in the default locale. + * + * @return A BreakIterator instance for the default locale. + */ public static BreakIterator getWordInstance () { return getWordInstance (Locale.getDefault()); } + /** + * This method returns an instance of BreakIterator that will + * iterate over words as defined in the specified locale. If the + * desired locale is not available, the default locale is used. + * + * @param locale The desired locale. + * + * @return A BreakIterator instance for the default locale. + */ public static BreakIterator getWordInstance (Locale loc) { BreakIterator r = getInstance ("WordIterator", loc); if (r == null) - r = new gnu.gcj.text.WordBreakIterator (); + r = new gnu.java.text.WordBreakIterator (); return r; } + /** + * This method tests whether or not the specified position is a text + * element boundary. + * + * @param offset The text position to test. + * + * @return true if the position is a boundary, + * false otherwise. + */ public boolean isBoundary (int pos) { if (pos == 0) @@ -135,10 +272,41 @@ public abstract class BreakIterator implements Cloneable return following (pos - 1) == pos; } + /** + * This method returns the last text element boundary in the text being + * iterated over. + * + * @return The last text boundary. + */ public abstract int last (); + + /** + * This method returns the text element boundary following the current + * text position. + * + * @return The next text boundary. + */ public abstract int next (); + + /** + * This method returns the n'th text element boundary following the current + * text position. + * + * @param n The number of text element boundaries to skip. + * + * @return The next text boundary. + */ public abstract int next (int n); + /** + * This methdod returns the offset of the text element boundary preceding + * the specified offset. + * + * @param offset The text index from which to find the preceding + * text boundary. + * + * @returns The next text boundary preceding the specified index. + */ public int preceding (int pos) { if (following (pos) == DONE) @@ -148,12 +316,29 @@ public abstract class BreakIterator implements Cloneable return current (); } + /** + * This method returns the text element boundary preceding the current + * text position. + * + * @return The previous text boundary. + */ public abstract int previous (); + /** + * This method sets the text string to iterate over. + * + * @param str The String to iterate over. + */ public void setText (String newText) { setText (new StringCharacterIterator (newText)); } + /** + * This method sets the text to iterate over from the specified + * CharacterIterator. + * + * @param ci The desired CharacterIterator. + */ public abstract void setText (CharacterIterator newText); } diff --git a/libjava/java/text/CharacterIterator.java b/libjava/java/text/CharacterIterator.java index a10ee4ad332..5ab79741045 100644 --- a/libjava/java/text/CharacterIterator.java +++ b/libjava/java/text/CharacterIterator.java @@ -1,36 +1,163 @@ -// CharacterIterator.java - Protocol for iterating over Unicode characters. +/* CharacterIterator.java -- Iterate over a character range + Copyright (C) 1998, 2001 Free Software Foundation, Inc. -/* Copyright (C) 1999 Free Software Foundation +This file is part of GNU Classpath. - This file is part of libgcj. +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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ package java.text; /** - * @author Tom Tromey - * @date February 22, 1999 - */ -/* Written using "Java Class Libraries", 2nd edition, plus online - * API docs for JDK 1.2 beta from http://www.javasoft.com. - * Status: Believed complete and correct to 1.1. - */ - + * This interface defines a mechanism for iterating over a range of + * characters. For a given range of text, a beginning and ending index, + * as well as a current index are defined. These values can be queried + * by the methods in this interface. Additionally, various methods allow + * the index to be set. + * + * @version 0.0 + * + * @author Aaron M. Renn (arenn@urbanophile.com) + */ public interface CharacterIterator extends Cloneable { - public abstract Object clone (); + + /*************************************************************************/ + + /* + * Static Variables + */ + + /** + * This is a special constant value that is returned when the beginning or + * end of the character range has been reached. + */ + public static final char DONE = '\uFFFF'; + + /*************************************************************************/ + + /* + * Instance Methods + */ + + /** + * This method returns the character at the current index position + * + * @return The character at the current index position. + */ public abstract char current (); + + /*************************************************************************/ + + /** + * This method increments the current index and then returns the character + * at the new index value. If the index is already at getEndIndex() - 1, + * it will not be incremented. + * + * @return The character at the position of the incremented index value, or DONE if the index has reached getEndIndex() - 1 + */ + public abstract char next (); + + /*************************************************************************/ + + /** + * This method decrements the current index and then returns the character + * at the new index value. If the index value is already at the beginning + * index, it will not be decremented. + * + * @return The character at the position of the decremented index value, or DONE if index was already equal to the beginning index value. + */ + public abstract char previous (); + + /*************************************************************************/ + + /** + * This method sets the index value to the beginning of the range and returns + * the character there. + * + * @return The character at the beginning of the range, or DONE if the range is empty. + */ public abstract char first (); + + /*************************************************************************/ + + /** + * This method sets the index value to getEndIndex() - 1 and + * returns the character there. If the range is empty, then the index value + * will be set equal to the beginning index. + * + * @return The character at the end of the range, or DONE if the range is empty. + */ + public abstract char last (); + + /*************************************************************************/ + + /** + * This method returns the current value of the index. + * + * @return The current index value + */ + public abstract int getIndex (); + + /*************************************************************************/ + + /** + * This method sets the value of the index to the specified value, then + * returns the character at that position. + * + * @param index The new index value. + * + * @return The character at the new index value or DONE if the index value is equal to getEndIndex. + */ + public abstract char setIndex (int index) throws IllegalArgumentException; + + /*************************************************************************/ + + /** + * This method returns the character position of the first character in the + * range. + * + * @return The index of the first character in the range. + */ public abstract int getBeginIndex (); + + /*************************************************************************/ + + /** + * This method returns the character position of the end of the text range. + * This will actually be the index of the first character following the + * end of the range. In the event the text range is empty, this will be + * equal to the first character in the range. + * + * @return The index of the end of the range. + */ public abstract int getEndIndex (); - public abstract int getIndex (); - public abstract char last (); - public abstract char next (); - public abstract char previous (); - public abstract char setIndex (int idx); - public static final char DONE = '\uffff'; + /*************************************************************************/ + + /** + * This method creates a copy of this CharacterIterator. + * + * @return A copy of this CharacterIterator. + */ + public abstract Object clone (); } diff --git a/libjava/java/text/ChoiceFormat.java b/libjava/java/text/ChoiceFormat.java index 584ece5c0e4..8e2d920bbcf 100644 --- a/libjava/java/text/ChoiceFormat.java +++ b/libjava/java/text/ChoiceFormat.java @@ -1,306 +1,487 @@ -// ChoiceFormat.java - Formatter for `switch'-like string substitution. +/* ChoiceFormat.java -- Format over a range of numbers + Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. -/* Copyright (C) 1999, 2000 Free Software Foundation +This file is part of GNU Classpath. - This file is part of libgcj. +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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -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.Vector; /** + * This class allows a format to be specified based on a range of numbers. + * To use this class, first specify two lists of formats and range terminators. + * These lists must be arrays of equal length. The format of index + * i will be selected for value X if + * terminator[i] <= X < limit[i + 1]. If the value X is not + * included in any range, then either the first or last format will be + * used depending on whether the value X falls outside the range. + *

+ * This sounds complicated, but that is because I did a poor job of + * explaining it. Consider the following example: + *

+ *

+ * terminators = { 1, ChoiceFormat.nextDouble(1) }
+ * formats = { "file", "files" }
+ * 
+ *

+ * In this case if the actual number tested is one or less, then the word + * "file" is used as the format value. If the number tested is greater than + * one, then "files" is used. This allows plurals to be handled + * gracefully. Note the use of the method nextDouble. This + * method selects the next highest double number than its argument. This + * effectively makes any double greater than 1.0 cause the "files" string + * to be selected. (Note that all terminator values are specified as + * doubles. + *

+ * Note that in order for this class to work properly, the range terminator + * array must be sorted in ascending order and the format string array + * must be the same length as the terminator array. + * * @author Tom Tromey + * @author Aaron M. Renn (arenn@urbanophile.com) * @date March 9, 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.1. */ - public class ChoiceFormat extends NumberFormat { - // Note: we assume the same kind of quoting rules apply here. - // This isn't explicitly documented. But for instance we accept - // '#' as a literal hash in a format string. + /** + * This method sets new range terminators and format strings for this + * object based on the specified pattern. This pattern is of the form + * "term#string|term#string...". For example "1#Sunday|2#Monday|#Tuesday". + * + * @param pattern The pattern of terminators and format strings. + * + * @exception IllegalArgumentException If the pattern is not valid + */ public void applyPattern (String newPattern) - { - int index = 0, max = newPattern.length(); - Vector stringVec = new Vector (); - Vector limitVec = new Vector (); - StringBuffer buf = new StringBuffer (); - - while (true) - { - // Find end of double. - int dstart = index; - while (index < max) - { - char c = newPattern.charAt(index); - if (c == '#' || c == '\u2064' || c == '<') - break; - ++index; - } - - if (index == max) - throw new IllegalArgumentException ("unexpected end of text"); - Double d = new Double (newPattern.substring(dstart, index)); - - if (newPattern.charAt(index) == '<') - d = new Double (nextDouble (d.doubleValue())); - - limitVec.addElement(d); - - // Scan text. - ++index; - buf.setLength(0); - while (index < max) - { - char c = newPattern.charAt(index); - if (c == '\'' && index < max + 1 - && newPattern.charAt(index + 1) == '\'') - { - buf.append(c); - ++index; - } - else if (c == '\'' && index < max + 2) - { - buf.append(newPattern.charAt(index + 1)); - index += 2; - } - else if (c == '|') - break; - else + { + // Note: we assume the same kind of quoting rules apply here. + // This isn't explicitly documented. But for instance we accept + // '#' as a literal hash in a format string. + int index = 0, max = newPattern.length(); + Vector stringVec = new Vector (); + Vector limitVec = new Vector (); + StringBuffer buf = new StringBuffer (); + + while (true) + { + // Find end of double. + int dstart = index; + while (index < max) + { + char c = newPattern.charAt(index); + if (c == '#' || c == '\u2064' || c == '<') + break; + ++index; + } + + if (index == max) + throw new IllegalArgumentException ("unexpected end of text"); + Double d = new Double (newPattern.substring(dstart, index)); + + if (newPattern.charAt(index) == '<') + d = new Double (nextDouble (d.doubleValue())); + + limitVec.addElement(d); + + // Scan text. + ++index; + buf.setLength(0); + while (index < max) + { + char c = newPattern.charAt(index); + if (c == '\'' && index < max + 1 + && newPattern.charAt(index + 1) == '\'') + { buf.append(c); - ++index; - } - - stringVec.addElement(buf.toString()); - if (index == max) - break; - ++index; - } - - choiceFormats = new String[stringVec.size()]; - stringVec.copyInto(choiceFormats); - - choiceLimits = new double[limitVec.size()]; - for (int i = 0; i < choiceLimits.length; ++i) - { - Double d = (Double) limitVec.elementAt(i); - choiceLimits[i] = d.doubleValue(); - } - } - + ++index; + } + else if (c == '\'' && index < max + 2) + { + buf.append(newPattern.charAt(index + 1)); + index += 2; + } + else if (c == '|') + break; + else + buf.append(c); + ++index; + } + + stringVec.addElement(buf.toString()); + if (index == max) + break; + ++index; + } + + choiceFormats = new String[stringVec.size()]; + stringVec.copyInto(choiceFormats); + + choiceLimits = new double[limitVec.size()]; + for (int i = 0; i < choiceLimits.length; ++i) + { + Double d = (Double) limitVec.elementAt(i); + choiceLimits[i] = d.doubleValue(); + } + } + + /** + * This method initializes a new instance of ChoiceFormat that + * generates its range terminator and format string arrays from the + * specified pattern. This pattern is of the form + * "term#string|term#string...". For example "1#Sunday|2#Monday|#Tuesday". + * This is the same pattern type used by the applyPattern + * method. + * + * @param pattern The pattern of terminators and format strings. + * + * @exception IllegalArgumentException If the pattern is not valid + */ public ChoiceFormat (String newPattern) - { - super (); - applyPattern (newPattern); - } - + { + super (); + applyPattern (newPattern); + } + + /** + * This method initializes a new instance of ChoiceFormat that + * will use the specified range terminators and format strings. + * + * @param choiceLimits The array of range terminators + * @param choiceFormats The array of format strings + */ public ChoiceFormat (double[] choiceLimits, String[] choiceFormats) - { - super (); - setChoices (choiceLimits, choiceFormats); - } - - public Object clone () - { - return new ChoiceFormat (choiceLimits, choiceFormats); - } - + { + super (); + setChoices (choiceLimits, choiceFormats); + } + + /** + * This method tests this object for equality with the specified + * object. This will be true if and only if: + *

    + *
  • The specified object is not null. + *
  • The specified object is an instance of ChoiceFormat. + *
  • The termination ranges and format strings are identical to + * this object's. + *
+ * + * @param obj The object to test for equality against. + * + * @return true if the specified object is equal to + * this one, false otherwise. + */ public boolean equals (Object obj) - { - if (! (obj instanceof ChoiceFormat)) - return false; - ChoiceFormat cf = (ChoiceFormat) obj; - if (choiceLimits.length != cf.choiceLimits.length) - return false; - for (int i = choiceLimits.length - 1; i >= 0; --i) - { - if (choiceLimits[i] != cf.choiceLimits[i] - || !choiceFormats[i].equals(cf.choiceFormats[i])) - return false; - } - return true; - } - + { + if (! (obj instanceof ChoiceFormat)) + return false; + ChoiceFormat cf = (ChoiceFormat) obj; + if (choiceLimits.length != cf.choiceLimits.length) + return false; + for (int i = choiceLimits.length - 1; i >= 0; --i) + { + if (choiceLimits[i] != cf.choiceLimits[i] + || !choiceFormats[i].equals(cf.choiceFormats[i])) + return false; + } + return true; + } + + /** + * This method appends the appropriate format string to the specified + * StringBuffer based on the supplied long + * argument. + * + * @param number The number used for determine (based on the range + * terminators) which format string to append. + * @param sb The StringBuffer to append the format string to. + * @param status Unused. + * + * @return The StringBuffer with the format string appended. + */ public StringBuffer format (long num, StringBuffer appendBuf, FieldPosition pos) - { - return format ((double) num, appendBuf, pos); - } - + { + return format ((double) num, appendBuf, pos); + } + + /** + * This method appends the appropriate format string to the specified + * StringBuffer based on the supplied double + * argument. + * + * @param number The number used for determine (based on the range + * terminators) which format string to append. + * @param sb The StringBuffer to append the format string to. + * @param status Unused. + * + * @return The StringBuffer with the format string appended. + */ public StringBuffer format (double num, StringBuffer appendBuf, FieldPosition pos) - { - if (choiceLimits.length == 0) - return appendBuf; - - int index = 0; - if (! Double.isNaN(num) && num >= choiceLimits[0]) - { - for (; index < choiceLimits.length - 1; ++index) - { - if (choiceLimits[index] <= num - && index != choiceLimits.length - 2 - && num < choiceLimits[index + 1]) - break; - } - } - - return appendBuf.append(choiceFormats[index]); - } - + { + if (choiceLimits.length == 0) + return appendBuf; + + int index = 0; + if (! Double.isNaN(num) && num >= choiceLimits[0]) + { + for (; index < choiceLimits.length - 1; ++index) + { + if (choiceLimits[index] <= num + && index != choiceLimits.length - 2 + && num < choiceLimits[index + 1]) + break; + } + } + + return appendBuf.append(choiceFormats[index]); + } + + /** + * This method returns the list of format strings in use. + * + * @return The list of format objects. + */ public Object[] getFormats () - { - return (Object[]) choiceFormats.clone(); - } - + { + return (Object[]) choiceFormats.clone(); + } + + /** + * This method returns the list of range terminators in use. + * + * @return The list of range terminators. + */ public double[] getLimits () - { - return (double[]) choiceLimits.clone(); - } - + { + return (double[]) choiceLimits.clone(); + } + + /** + * This method returns a hash value for this object + * + * @return A hash value for this object. + */ public int hashCode () - { - int hash = 0; - for (int i = 0; i < choiceLimits.length; ++i) - { - long v = Double.doubleToLongBits(choiceLimits[i]); - hash ^= (v ^ (v >>> 32)); - hash ^= choiceFormats[i].hashCode(); - } - return hash; - } - + { + int hash = 0; + for (int i = 0; i < choiceLimits.length; ++i) + { + long v = Double.doubleToLongBits(choiceLimits[i]); + hash ^= (v ^ (v >>> 32)); + hash ^= choiceFormats[i].hashCode(); + } + return hash; + } + + /** + * This method returns the lowest possible double greater than the + * specified double. If the specified double value is equal to + * Double.NaN then that is the value returned. + * + * @param d The specified double + * + * @return The lowest double value greater than the specified double. + */ public static final double nextDouble (double d) - { - return nextDouble (d, true); - } - + { + return nextDouble (d, true); + } + + /** + * This method returns a double that is either the next highest double + * or next lowest double compared to the specified double depending on the + * value of the passed boolean parameter. If the boolean parameter is + * true, then the lowest possible double greater than the + * specified double will be returned. Otherwise the highest possible + * double less than the specified double will be returned. + * + * @param d The specified double + * @param positive true to return the next highest + * double, false otherwise. + * + * @return The next highest or lowest double value. + */ public static double nextDouble (double d, boolean next) - { - if (Double.isInfinite(d) || Double.isNaN(d)) - return d; + { + if (Double.isInfinite(d) || Double.isNaN(d)) + return d; - long bits = Double.doubleToLongBits(d); + long bits = Double.doubleToLongBits(d); - long mantMask = (1L << mantissaBits) - 1; - long mantissa = bits & mantMask; + long mantMask = (1L << mantissaBits) - 1; + long mantissa = bits & mantMask; - long expMask = (1L << exponentBits) - 1; - long exponent = (bits >>> mantissaBits) & expMask; + long expMask = (1L << exponentBits) - 1; + long exponent = (bits >>> mantissaBits) & expMask; - if (next ^ (bits < 0)) // Increment magnitude - { - if (mantissa == (1L << mantissaBits) - 1) - { - mantissa = 0L; - exponent++; + if (next ^ (bits < 0)) // Increment magnitude + { + if (mantissa == (1L << mantissaBits) - 1) + { + mantissa = 0L; + exponent++; - // Check for absolute overflow. - if (exponent >= (1L << mantissaBits)) - return (bits > 0) ? Double.POSITIVE_INFINITY - : Double.NEGATIVE_INFINITY; - } - else - mantissa++; - } - else // Decrement magnitude - { - if (exponent == 0L && mantissa == 0L) - { - // The only case where there is a change of sign - return next ? Double.MIN_VALUE : -Double.MIN_VALUE; - } - else - { - if (mantissa == 0L) - { - mantissa = (1L << mantissaBits) - 1; - exponent--; - } - else - mantissa--; - } - } - - long result = bits < 0 ? 1 : 0; - result = (result << exponentBits) | exponent; - result = (result << mantissaBits) | mantissa; - return Double.longBitsToDouble(result); - } - + // Check for absolute overflow. + if (exponent >= (1L << mantissaBits)) + return (bits > 0) ? Double.POSITIVE_INFINITY + : Double.NEGATIVE_INFINITY; + } + else + mantissa++; + } + else // Decrement magnitude + { + if (exponent == 0L && mantissa == 0L) + { + // The only case where there is a change of sign + return next ? Double.MIN_VALUE : -Double.MIN_VALUE; + } + else + { + if (mantissa == 0L) + { + mantissa = (1L << mantissaBits) - 1; + exponent--; + } + else + mantissa--; + } + } + + long result = bits < 0 ? 1 : 0; + result = (result << exponentBits) | exponent; + result = (result << mantissaBits) | mantissa; + return Double.longBitsToDouble(result); + } + + /** + * I'm not sure what this method is really supposed to do, as it is + * not documented. + */ public Number parse (String sourceStr, ParsePosition pos) - { - int index = pos.getIndex(); - for (int i = 0; i < choiceLimits.length; ++i) - { - if (sourceStr.startsWith(choiceFormats[i], index)) - { - pos.setIndex(index + choiceFormats[i].length()); - return new Double (choiceLimits[i]); - } - } - pos.setErrorIndex(index); - return new Double (Double.NaN); - } - + { + int index = pos.getIndex(); + for (int i = 0; i < choiceLimits.length; ++i) + { + if (sourceStr.startsWith(choiceFormats[i], index)) + { + pos.setIndex(index + choiceFormats[i].length()); + return new Double (choiceLimits[i]); + } + } + pos.setErrorIndex(index); + return new Double (Double.NaN); + } + + /** + * This method returns the highest possible double less than the + * specified double. If the specified double value is equal to + * Double.NaN then that is the value returned. + * + * @param d The specified double + * + * @return The highest double value less than the specified double. + */ public static final double previousDouble (double d) - { - return nextDouble (d, false); - } - + { + return nextDouble (d, false); + } + + /** + * This method sets new range terminators and format strings for this + * object. + * + * @param choiceLimits The new range terminators + * @param choiceFormats The new choice formats + */ public void setChoices (double[] choiceLimits, String[] choiceFormats) - { - if (choiceLimits == null || choiceFormats == null) - throw new NullPointerException (); - if (choiceLimits.length != choiceFormats.length) - throw new IllegalArgumentException (); - this.choiceFormats = (String[]) choiceFormats.clone(); - this.choiceLimits = (double[]) choiceLimits.clone(); - } + { + if (choiceLimits == null || choiceFormats == null) + throw new NullPointerException (); + if (choiceLimits.length != choiceFormats.length) + throw new IllegalArgumentException (); + this.choiceFormats = (String[]) choiceFormats.clone(); + this.choiceLimits = (double[]) choiceLimits.clone(); + } private final void quoteString (StringBuffer dest, String text) - { - int max = text.length(); - for (int i = 0; i < max; ++i) - { - char c = text.charAt(i); - if (c == '\'') - { - dest.append(c); - dest.append(c); - } - else if (c == '#' || c == '|' || c == '\u2064' || c == '<') - { - dest.append('\''); - dest.append(c); - dest.append('\''); - } - else + { + int max = text.length(); + for (int i = 0; i < max; ++i) + { + char c = text.charAt(i); + if (c == '\'') + { dest.append(c); - } - } - + dest.append(c); + } + else if (c == '#' || c == '|' || c == '\u2064' || c == '<') + { + dest.append('\''); + dest.append(c); + dest.append('\''); + } + else + dest.append(c); + } + } + + /** + * This method returns the range terminator list and format string list + * as a String suitable for using with the + * applyPattern method. + * + * @return A pattern string for this object + */ public String toPattern () - { - StringBuffer result = new StringBuffer (); - for (int i = 0; i < choiceLimits.length; ++i) - { - result.append(choiceLimits[i]); - result.append('#'); - quoteString (result, choiceFormats[i]); - } - return result.toString(); - } - - // Formats and limits. + { + StringBuffer result = new StringBuffer (); + for (int i = 0; i < choiceLimits.length; ++i) + { + result.append(choiceLimits[i]); + result.append('#'); + quoteString (result, choiceFormats[i]); + } + return result.toString(); + } + + /** + * This is the list of format strings. Note that this variable is + * specified by the serialization spec of this class. + */ private String[] choiceFormats; + + /** + * This is the list of range terminator values. Note that this variable is + * specified by the serialization spec of this class. + */ private double[] choiceLimits; // Number of mantissa bits in double. diff --git a/libjava/java/text/Collator.java b/libjava/java/text/Collator.java index 9a356c16541..51a053dcf18 100644 --- a/libjava/java/text/Collator.java +++ b/libjava/java/text/Collator.java @@ -1,12 +1,29 @@ -// Collator.java - Locale-sensitive string comparison. +/* Collator.java -- Perform locale dependent String comparisons. + Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. -/* Copyright (C) 1999, 2000 Free Software Foundation +This file is part of GNU Classpath. - This file is part of libgcj. +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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ package java.text; @@ -16,38 +33,157 @@ import java.util.ResourceBundle; import java.util.Comparator; /** + * This class is the abstract superclass of classes which perform + * locale dependent String comparisons. A caller requests + * an instance of Collator for a particular locale using + * the getInstance() static method in this class. That method + * will return a locale specific subclass of Collator which + * can be used to perform String comparisons for that locale. + * If a subclass of Collator cannot be located for a particular + * locale, a default instance for the current locale will be returned. + * + * In addition to setting the correct locale, there are two additional + * settings that can be adjusted to affect String comparisons: + * strength and decomposition. The strength value determines the level + * of signficance of character differences required for them to sort + * differently. (For example, whether or not capital letters are considered + * different from lower case letters). The decomposition value affects how + * variants of the same character are treated for sorting purposes. (For + * example, whether or not an accent is signficant or not). These settings + * are described in detail in the documentation for the methods and values + * that are related to them. + * * @author Tom Tromey + * @author Aaron M. Renn (arenn@urbanophile.com) * @date March 18, 1999 */ /* Written using "Java Class Libraries", 2nd edition, plus online * API docs for JDK 1.2 from http://www.javasoft.com. * Status: Mostly complete, but parts stubbed out. Look for FIXME. */ - public abstract class Collator implements Comparator, Cloneable { - public static final int NO_DECOMPOSITION = 0; - public static final int CANONICAL_DECOMPOSITION = 1; - public static final int FULL_DECOMPOSITION = 2; - + /** + * This constant is a strength value which indicates that only primary + * differences between characters will be considered signficant. As an + * example, two completely different English letters such as 'a' and 'b' + * are considered to have a primary difference. + */ public static final int PRIMARY = 0; + + /** + * This constant is a strength value which indicates that only secondary + * or primary differences between characters will be considered + * significant. An example of a secondary difference between characters + * are instances of the same letter with different accented forms. + */ public static final int SECONDARY = 1; + + /** + * This constant is a strength value which indicates that tertiary, + * secondary, and primary differences will be considered during sorting. + * An example of a tertiary difference is capitalization of a given letter. + * This is the default value for the strength setting. + */ public static final int TERTIARY = 2; + + /** + * This constant is a strength value which indicates that any difference + * at all between character values are considered significant. + */ public static final int IDENTICAL = 3; + + /** + * This constant indicates that accented characters won't be decomposed + * when performing comparisons. This will yield the fastest results, but + * will only work correctly in call cases for languages which do not + * use accents such as English. + */ + public static final int NO_DECOMPOSITION = 0; + + /** + * This constant indicates that only characters which are canonical variants + * in Unicode 2.0 will be decomposed prior to performing comparisons. This + * will cause accented languages to be sorted correctly. This is the + * default decomposition value. + */ + public static final int CANONICAL_DECOMPOSITION = 1; + + /** + * This constant indicates that both canonical variants and compatibility + * variants in Unicode 2.0 will be decomposed prior to performing + * comparisons. This is the slowest mode, but is required to get the + * correct sorting for certain languages with certain special formats. + */ + public static final int FULL_DECOMPOSITION = 2; + /** + * This method initializes a new instance of Collator to have + * the default strength (TERTIARY) and decomposition + * (CANONICAL_DECOMPOSITION) settings. This constructor is protected and + * is for use by subclasses only. Non-subclass callers should use the + * static getInstance() methods of this class to instantiate + * Collation objects for the desired locale. + */ protected Collator () { strength = TERTIARY; decmp = CANONICAL_DECOMPOSITION; } + /** + * This method compares the two String's and returns an + * integer indicating whether or not the first argument is less than, + * equal to, or greater than the second argument. The comparison is + * performed according to the rules of the locale for this + * Collator and the strength and decomposition rules in + * effect. + * + * @param str1 The first object to compare + * @param str2 The second object to compare + * + * @return A negative integer if str1 < str2, 0 if str1 == str2, or + * a positive integer if str1 > str2. + */ public abstract int compare (String source, String target); + /** + * This method compares the two Object's and returns an + * integer indicating whether or not the first argument is less than, + * equal to, or greater than the second argument. These two objects + * must be String's or an exception will be thrown. + * + * @param obj1 The first object to compare + * @param obj2 The second object to compare + * + * @return A negative integer if obj1 < obj2, 0 if obj1 == obj2, or + * a positive integer if obj1 > obj2. + * + * @exception ClassCastException If the arguments are not instances + * of String. + */ public int compare (Object o1, Object o2) { return compare ((String) o1, (String) o2); } + /** + * This method tests the specified object for equality against this + * object. This will be true if and only if the following conditions are + * met: + *
    + *
  • The specified object is not null. + *
  • The specified object is an instance of Collator. + *
  • The specified object has the same strength and decomposition + * settings as this object. + *
+ * + * @param obj The Object to test for equality against + * this object. + * + * @return true if the specified object is equal to + * this one, false otherwise. + */ public boolean equals (Object obj) { if (! (obj instanceof Collator)) @@ -56,42 +192,108 @@ public abstract class Collator implements Comparator, Cloneable return decmp == c.decmp && strength == c.strength; } + /** + * This method tests whether the specified String's are equal + * according to the collation rules for the locale of this object and + * the current strength and decomposition settings. + * + * @param str1 The first String to compare + * @param str2 The second String to compare + * + * @return true if the two strings are equal, + * false otherwise. + */ public boolean equals (String source, String target) { return compare (source, target) == 0; } + /** + * This method returns a copy of this Collator object. + * + * @return A duplicate of this object. + */ public Object clone () { - return super.clone (); + try + { + return super.clone (); + } + catch (CloneNotSupportedException _) + { + return null; + } } + /** + * This method returns an array of Locale objects which is + * the list of locales for which Collator objects exist. + * + * @return The list of locales for which Collator's exist. + */ public static synchronized Locale[] getAvailableLocales () { - // FIXME. - return null; + // FIXME + Locale[] l = new Locale[1]; + l[0] = Locale.US; + return l; } + /** + * This method transforms the specified String into a + * CollationKey for faster comparisons. This is useful when + * comparisons against a string might be performed multiple times, such + * as during a sort operation. + * + * @param str The String to convert. + * + * @return A CollationKey for the specified String. + */ public abstract CollationKey getCollationKey (String source); + /** + * This method returns the current decomposition setting for this + * object. This * will be one of NO_DECOMPOSITION, + * CANONICAL_DECOMPOSITION, or * FULL_DECOMPOSITION. See the + * documentation for those constants for an * explanation of this + * setting. + * + * @return The current decomposition setting. + */ public synchronized int getDecomposition () { return decmp; } + /** + * This method returns an instance of Collator for the + * default locale. + * + * @return A Collator for the default locale. + */ public static Collator getInstance () { return getInstance (Locale.getDefault()); } + /** + * This method returns an instance of Collator for the + * specified locale. If no Collator exists for the desired + * locale, a Collator for the default locale will be returned. + * + * @param locale The desired localed to load a Collator for. + * + * @return A Collator for the requested locale + */ public static Collator getInstance (Locale loc) { ResourceBundle res; String pattern; try { - res = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", loc); - pattern = res.getString("collatorRule"); + res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", + loc); + pattern = res.getString("collation_rules"); } catch (MissingResourceException x) { @@ -107,13 +309,37 @@ public abstract class Collator implements Comparator, Cloneable } } + /** + * This method returns the current strength setting for this object. This + * will be one of PRIMARY, SECONDARY, TERTIARY, or IDENTICAL. See the + * documentation for those constants for an explanation of this setting. + * + * @return The current strength setting. + */ public synchronized int getStrength () { return strength; } + /** + * This method returns a hash code value for this object. + * + * @return A hash value for this object. + */ public abstract int hashCode (); + /** + * This method sets the decomposition setting for this object to the + * specified value. This must be one of NO_DECOMPOSITION, + * CANONICAL_DECOMPOSITION, or FULL_DECOMPOSITION. Otherwise an + * exception will be thrown. See the documentation for those + * contants for an explanation of this setting. + * + * @param decmp The new decomposition setting. + * + * @exception IllegalArgumentException If the requested + * decomposition setting is not valid. + */ public synchronized void setDecomposition (int mode) { if (mode != NO_DECOMPOSITION @@ -123,6 +349,17 @@ public abstract class Collator implements Comparator, Cloneable decmp = mode; } + /** + * This method sets the strength setting for this object to the specified + * value. This must be one of PRIMARY, SECONDARY, TERTIARY, or IDENTICAL. + * Otherwise an exception is thrown. See the documentation for these + * constants for an explanation of this setting. + * + * @param strength The new strength setting. + * + * @exception IllegalArgumentException If the requested strength + * setting value is not valid. + */ public synchronized void setStrength (int strength) { if (strength != PRIMARY && strength != SECONDARY @@ -134,7 +371,13 @@ public abstract class Collator implements Comparator, Cloneable // Decompose a single character and append results to the buffer. native final void decomposeCharacter (char c, StringBuffer buf); - // These names are fixed by the serialization spec. + /** + * This is the current collation decomposition setting. + */ int decmp; + + /** + * This is the current collation strength setting. + */ int strength; } diff --git a/libjava/java/text/DateFormat.java b/libjava/java/text/DateFormat.java index 604a1d5b2e5..0e84f87ac33 100644 --- a/libjava/java/text/DateFormat.java +++ b/libjava/java/text/DateFormat.java @@ -1,10 +1,29 @@ -/* Copyright (C) 1998, 1999, 2000 Free Software Foundation +/* DateFormat.java -- Class for formatting/parsing date/times + Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - This file is part of libgcj. +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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ package java.text; @@ -25,35 +44,60 @@ public abstract class DateFormat extends Format implements Cloneable protected NumberFormat numberFormat; // (Values determined using a test program.) - public final static int FULL = 0; - public final static int LONG = 1; - public final static int MEDIUM = 2; - public final static int SHORT = 3; - public final static int DEFAULT = MEDIUM; - - public final static int ERA_FIELD = 0; - public final static int YEAR_FIELD = 1; - public final static int MONTH_FIELD = 2; - public final static int DATE_FIELD = 3; - public final static int HOUR_OF_DAY1_FIELD = 4; - public final static int HOUR_OF_DAY0_FIELD = 5; - public final static int MINUTE_FIELD = 6; - public final static int SECOND_FIELD = 7; - public final static int MILLISECOND_FIELD = 8; - public final static int DAY_OF_WEEK_FIELD = 9; - public final static int DAY_OF_YEAR_FIELD = 10; - public final static int DAY_OF_WEEK_IN_MONTH_FIELD = 11; - public final static int WEEK_OF_YEAR_FIELD = 12; - public final static int WEEK_OF_MONTH_FIELD = 13; - public final static int AM_PM_FIELD = 14; - public final static int HOUR1_FIELD = 15; - public final static int HOUR0_FIELD = 16; - public final static int TIMEZONE_FIELD = 17; - + public static final int FULL = 0; + public static final int LONG = 1; + public static final int MEDIUM = 2; + public static final int SHORT = 3; + public static final int DEFAULT = MEDIUM; + + /* These constants need to have these exact values. They + * correspond to index positions within the localPatternChars + * string for a given locale. For example, the US locale uses + * the string "GyMdkHmsSEDFwWahKz", where 'G' is the character + * for era, 'y' for year, and so on down to 'z' for time zone. + */ + public static final int ERA_FIELD = 0; + public static final int YEAR_FIELD = 1; + public static final int MONTH_FIELD = 2; + public static final int DATE_FIELD = 3; + public static final int HOUR_OF_DAY1_FIELD = 4; + public static final int HOUR_OF_DAY0_FIELD = 5; + public static final int MINUTE_FIELD = 6; + public static final int SECOND_FIELD = 7; + public static final int MILLISECOND_FIELD = 8; + public static final int DAY_OF_WEEK_FIELD = 9; + public static final int DAY_OF_YEAR_FIELD = 10; + public static final int DAY_OF_WEEK_IN_MONTH_FIELD = 11; + public static final int WEEK_OF_YEAR_FIELD = 12; + public static final int WEEK_OF_MONTH_FIELD = 13; + public static final int AM_PM_FIELD = 14; + public static final int HOUR1_FIELD = 15; + public static final int HOUR0_FIELD = 16; + public static final int TIMEZONE_FIELD = 17; + + /** + * This method initializes a new instance of DateFormat. + */ protected DateFormat () { } + /** + * This method tests this object for equality against the specified object. + * The two objects will be considered equal if an only if the specified + * object: + *

+ *

    + *
  • Is not null. + *
  • Is an instance of DateFormat. + *
  • Has the same calendar and numberFormat field values as this object. + *
+ * + * @param obj The object to test for equality against. + * + * @return true if the specified object is equal to this object, + * false otherwise. + */ public boolean equals (Object obj) { if (! (obj instanceof DateFormat)) @@ -62,20 +106,46 @@ public abstract class DateFormat extends Format implements Cloneable return calendar.equals(d.calendar) && numberFormat.equals(d.numberFormat); } + /** + * This method returns a copy of this object. + * + * @return A copy of this object. + */ public Object clone () { // We know the superclass just call's Object's generic cloner. return super.clone (); } + /** + * This method formats the specified Object into a date string + * and appends it to the specified StringBuffer. + * The specified object must be an instance of Number or + * Date or an IllegalArgumentException will be + * thrown. + * + * @param obj The Object to format. + * @param toAppendTo The StringBuffer to append the resultant + * String to. + * @param fieldPosition Is updated to the start and end index of the + * specified field. + * + * @return The StringBuffer supplied on input, with the + * formatted date/time appended. + */ public final StringBuffer format (Object obj, StringBuffer buf, FieldPosition pos) { if (obj instanceof Number) - return format (new Date(((Number) obj).longValue()), buf, pos); + obj = new Date(((Number) obj).longValue()); return format ((Date) obj, buf, pos); } + /** + * Formats the date argument according to the pattern specified. + * + * @param date The formatted date. + */ public final String format (Date date) { StringBuffer sb = new StringBuffer (); @@ -83,14 +153,42 @@ public abstract class DateFormat extends Format implements Cloneable return sb.toString(); } + /** + * This method formats a Date into a string and appends it + * to the specified StringBuffer. + * + * @param date The Date value to format. + * @param toAppendTo The StringBuffer to append the resultant + * String to. + * @param fieldPosition Is updated to the start and end index of the + * specified field. + * + * @return The StringBuffer supplied on input, with the + * formatted date/time appended. + */ public abstract StringBuffer format (Date date, StringBuffer buf, FieldPosition pos); + /** + * This method returns a list of available locales supported by this + * class. + */ public static Locale[] getAvailableLocales () { - return null; // FIXME + // FIXME + Locale[] l = new Locale[1]; + l[0] = Locale.US; + return l; } + /** + * This method returns the Calendar object being used by + * this object to parse/format datetimes. + * + * @return The Calendar being used by this object. + * + * @see java.util.Calendar + */ public Calendar getCalendar () { return calendar; @@ -112,7 +210,8 @@ public abstract class DateFormat extends Format implements Cloneable ResourceBundle res; try { - res = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", loc); + res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", + loc); } catch (MissingResourceException x) { @@ -199,32 +298,77 @@ public abstract class DateFormat extends Format implements Cloneable return new SimpleDateFormat (pattern, loc); } + /** + * This method returns an instance of DateFormat that will + * format using the default formatting style for dates. + * + * @return A new DateFormat instance. + */ public static final DateFormat getDateInstance () { return getDateInstance (DEFAULT, Locale.getDefault()); } + /** + * This method returns an instance of DateFormat that will + * format using the specified formatting style for dates. + * + * @param style The type of formatting to perform. + * + * @return A new DateFormat instance. + */ public static final DateFormat getDateInstance (int style) { return getDateInstance (style, Locale.getDefault()); } + /** + * This method returns an instance of DateFormat that will + * format using the specified formatting style for dates. The specified + * localed will be used in place of the default. + * + * @param style The type of formatting to perform. + * @param aLocale The desired locale. + * + * @return A new DateFormat instance. + */ public static final DateFormat getDateInstance (int style, Locale loc) { return computeInstance (style, loc, true, false); } + /** + * This method returns a new instance of DateFormat that + * formats both dates and times using the SHORT style. + * + * @return A new DateFormatinstance. + */ public static final DateFormat getDateTimeInstance () { return getDateTimeInstance (DEFAULT, DEFAULT, Locale.getDefault()); } + /** + * This method returns a new instance of DateFormat that + * formats both dates and times using the DEFAULT style. + * + * @return A new DateFormatinstance. + */ public static final DateFormat getDateTimeInstance (int dateStyle, int timeStyle) { return getDateTimeInstance (dateStyle, timeStyle, Locale.getDefault()); } + /** + * This method returns a new instance of DateFormat that + * formats both dates and times using the specified styles. + * + * @param dateStyle The desired style for date formatting. + * @param timeStyle The desired style for time formatting + * + * @return A new DateFormatinstance. + */ public static final DateFormat getDateTimeInstance (int dateStyle, int timeStyle, Locale loc) @@ -232,37 +376,84 @@ public abstract class DateFormat extends Format implements Cloneable return computeInstance (dateStyle, timeStyle, loc, true, true); } + /** + * This method returns a new instance of DateFormat that + * formats both dates and times using the SHORT style. + * + * @return A new DateFormatinstance. + */ public static final DateFormat getInstance () { // JCL book says SHORT. return getDateTimeInstance (SHORT, SHORT, Locale.getDefault()); } + /** + * This method returns the NumberFormat object being used + * by this object to parse/format time values. + * + * @return The NumberFormat in use by this object. + */ public NumberFormat getNumberFormat () { return numberFormat; } + /** + * This method returns an instance of DateFormat that will + * format using the default formatting style for times. + * + * @return A new DateFormat instance. + */ public static final DateFormat getTimeInstance () { return getTimeInstance (DEFAULT, Locale.getDefault()); } + /** + * This method returns an instance of DateFormat that will + * format using the specified formatting style for times. + * + * @param style The type of formatting to perform. + * + * @return A new DateFormat instance. + */ public static final DateFormat getTimeInstance (int style) { return getTimeInstance (style, Locale.getDefault()); } + /** + * This method returns an instance of DateFormat that will + * format using the specified formatting style for times. The specified + * localed will be used in place of the default. + * + * @param style The type of formatting to perform. + * @param aLocale The desired locale. + * + * @return A new DateFormat instance. + */ public static final DateFormat getTimeInstance (int style, Locale loc) { return computeInstance (style, loc, false, true); } + /** + * This method returns the TimeZone object being used by + * this instance. + * + * @return The time zone in use. + */ public TimeZone getTimeZone () { return calendar.getTimeZone(); } + /** + * This method returns a hash value for this object. + * + * @return A hash value for this object. + */ public int hashCode () { int hash = calendar.hashCode(); @@ -271,11 +462,25 @@ public abstract class DateFormat extends Format implements Cloneable return hash; } + /** + * This method indicates whether or not the parsing of date and time + * values should be done in a lenient value. + * + * @return true if date/time parsing is lenient, + * false otherwise. + */ public boolean isLenient () { return calendar.isLenient(); } + /** + * This method parses the specified date/time string. + * + * @return The resultant date. + * + * @exception ParseException If the specified string cannot be parsed. + */ public Date parse (String source) throws ParseException { ParsePosition pos = new ParsePosition(0); @@ -290,28 +495,79 @@ public abstract class DateFormat extends Format implements Cloneable return result; } + /** + * This method parses the specified String into a + * Date. The pos argument contains the + * starting parse position on method entry and the ending parse + * position on method exit. + * + * @param text The string to parse. + * @param pos The starting parse position in entry, the ending parse + * position on exit. + * + * @return The parsed date, or null if the string cannot + * be parsed. + */ public abstract Date parse (String source, ParsePosition pos); + /** + * This method is identical to parse(String, ParsePosition), + * but returns its result as an Object instead of a + * Date. + * + * @param source The string to parse. + * @param pos The starting parse position in entry, the ending parse + * position on exit. + * + * @return The parsed date, or null if the string cannot + * be parsed. + */ public Object parseObject (String source, ParsePosition pos) { return parse(source, pos); } + /** + * This method specified the Calendar that should be used + * by this object to parse/format datetimes. + * + * @param The new Calendar for this object. + * + * @see java.util.Calendar + */ public void setCalendar (Calendar calendar) { this.calendar = calendar; } + /** + * This method specifies whether or not this object should be lenient in + * the syntax it accepts while parsing date/time values. + * + * @param lenient true if parsing should be lenient, + * false otherwise. + */ public void setLenient (boolean lenient) { calendar.setLenient(lenient); } + /** + * This method specifies the NumberFormat object that should + * be used by this object to parse/format times. + * + * @param The NumberFormat in use by this object. + */ public void setNumberFormat (NumberFormat numberFormat) { this.numberFormat = numberFormat; } + /** + * This method sets the time zone that should be used by this object. + * + * @param The new time zone. + */ public void setTimeZone (TimeZone timeZone) { calendar.setTimeZone(timeZone); diff --git a/libjava/java/text/DateFormatSymbols.java b/libjava/java/text/DateFormatSymbols.java index 252f9fa7743..4f45a4dbfbd 100644 --- a/libjava/java/text/DateFormatSymbols.java +++ b/libjava/java/text/DateFormatSymbols.java @@ -1,4 +1,4 @@ -/* Copyright (C) 1998, 1999, 2000 Free Software Foundation +/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation This file is part of libgcj. @@ -13,16 +13,15 @@ import java.util.MissingResourceException; import java.util.ResourceBundle; /** + * This class acts as container for locale specific date/time formatting + * information such as the days of the week and the months of the year. * @author Per Bothner * @date October 24, 1998. */ - /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3. * Status: Believed complete and correct. */ - -public class DateFormatSymbols extends Object - implements java.io.Serializable, Cloneable +public class DateFormatSymbols implements java.io.Serializable, Cloneable { String[] ampms; String[] eras; @@ -36,63 +35,9 @@ public class DateFormatSymbols extends Object private static final long serialVersionUID = -5987973545549424702L; // The order of these prefixes must be the same as in DateFormat - // FIXME: XXX: Note that this differs from the Classpath implemention - // in that there is no "default" entry; that is due to differing - // implementations where DateFormat.DEFAULT is MEDIUM here but 4 in - // Classpath (the JCL says it should be MEDIUM). That will need to be - // resolved in the merge. - private static final String[] formatPrefixes = { "full", "long", "medium", "short" }; - - private static final String[] ampmsDefault = {"AM", "PM" }; - private static final String[] erasDefault = {"BC", "AD" }; - // localPatternCharsDefault is used by SimpleDateFormat. - private static final String localPatternCharsDefault - = "GyMdkHmsSEDFwWahKz"; - private static final String[] monthsDefault = { - "January", "February", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December", "" - }; - private static final String[] shortMonthsDefault = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "" - }; - private static final String[] shortWeekdaysDefault = { - "", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" - }; - private static final String[] weekdaysDefault = { - "", "Sunday", "Monday", "Tuesday", - "Wednesday", "Thursday", "Friday", "Saturday" - }; - - private static String[][] zoneStringsDefault = { - { "GMT", "Greenwich Mean Time", "GMT", - /**/ "Greenwich Mean Time", "GMT", "GMT" }, - { "PST", "Pacific Standard Time", "PST", - /**/ "Pacific Daylight Time", "PDT", "San Francisco" }, - { "MST", "Mountain Standard Time", "MST", - /**/ "Mountain Daylight Time", "MDT", "Denver" }, - { "PNT", "Mountain Standard Time", "MST", - /**/ "Mountain Standard Time", "MST", "Phoenix" }, - { "CST", "Central Standard Time", "CST", - /**/ "Central Daylight Time", "CDT", "Chicago" }, - { "EST", "Eastern Standard Time", "EST", - /**/ "Eastern Daylight Time", "EDT", "Boston" }, - { "IET", "Eastern Standard Time", "EST", - /**/ "Eastern Standard Time", "EST", "Indianapolis" }, - { "PRT", "Atlantic Standard Time", "AST", - /**/ "Atlantic Daylight Time", "ADT", "Halifax" }, - { "CNT", "Newfoundland Standard Time", "NST", - /**/ "Newfoundland Daylight Time", "NDT", "St. Johns" }, - { "ECT", "Central European Standard Time", "CET", - /**/ "Central European Daylight Time", "CEST", "Paris" }, - { "CTT", "China Standard Time", "CST", - /**/ "China Standard Time", "CST", "Shanghai" }, - { "JST", "Japan Standard Time", "JST", - /**/ "Japan Standard Time", "JST", "Tokyo" }, - { "HST", "Hawaii Standard Time", "HST", - /**/ "Hawaii Standard Time", "HST", "Honolulu" }, - { "AST", "Alaska Standard Time", "AKST", - /**/ "Alaska Daylight Time", "AKDT", "Anchorage" } + private static final String[] formatPrefixes = + { + "full", "long", "medium", "short" }; // These are each arrays with a value for SHORT, MEDIUM, LONG, FULL, @@ -113,146 +58,312 @@ public class DateFormatSymbols extends Object return values; } - private final Object safeGetResource (ResourceBundle res, - String key, Object def) - { - if (res != null) - { - try - { - return res.getObject(key); - } - catch (MissingResourceException x) - { - } - } - return def; - } - - public DateFormatSymbols (Locale locale) + /** + * This method initializes a new instance of DateFormatSymbols + * by loading the date format information for the specified locale. + * + * @param locale The locale for which date formatting symbols should + * be loaded. + */ + public DateFormatSymbols (Locale locale) throws MissingResourceException { - ResourceBundle res; - try - { - res = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", locale); - } - catch (MissingResourceException x) - { - res = null; - } - ampms = (String[]) safeGetResource (res, "ampm", ampmsDefault); - eras = (String[]) safeGetResource (res, "eras", erasDefault); - localPatternChars = (String) safeGetResource (res, "datePatternChars", - localPatternCharsDefault); - months = (String[]) safeGetResource (res, "months", monthsDefault); - shortMonths = (String[]) safeGetResource (res, "shortMonths", - shortMonthsDefault); - shortWeekdays = (String[]) safeGetResource (res, "shortWeekdays", - shortWeekdaysDefault); - weekdays = (String[]) safeGetResource (res, "weekdays", weekdaysDefault); - zoneStrings = (String[][]) safeGetResource (res, "zoneStrings", - zoneStringsDefault); + ResourceBundle res + = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", locale); + + ampms = res.getStringArray ("ampms"); + eras = res.getStringArray ("eras"); + localPatternChars = res.getString ("localPatternChars"); + months = res.getStringArray ("months"); + shortMonths = res.getStringArray ("shortMonths"); + shortWeekdays = res.getStringArray ("shortWeekdays"); + weekdays = res.getStringArray ("weekdays"); + zoneStrings = (String[][]) res.getObject ("zoneStrings"); dateFormats = formatsForKey(res, "DateFormat"); timeFormats = formatsForKey(res, "TimeFormat"); } - public DateFormatSymbols () + /** + * This method loads the format symbol information for the default + * locale. + */ + public DateFormatSymbols () throws MissingResourceException { this (Locale.getDefault()); } - // Copy constructor. - private DateFormatSymbols (DateFormatSymbols old) - { - ampms = old.ampms; - eras = old.eras; - localPatternChars = old.localPatternChars; - months = old.months; - shortMonths = old.shortMonths; - shortWeekdays = old.shortWeekdays; - weekdays = old.weekdays; - zoneStrings = old.zoneStrings; - dateFormats = old.dateFormats; - timeFormats = old.timeFormats; - } - + /** + * This method returns the list of strings used for displaying AM or PM. + * This is a two element String array indexed by + * Calendar.AM and Calendar.PM + * + * @return The list of AM/PM display strings. + */ public String[] getAmPmStrings() { return ampms; } + /** + * This method returns the list of strings used for displaying eras + * (e.g., "BC" and "AD"). This is a two element String + * array indexed by Calendar.BC and Calendar.AD. + * + * @return The list of era disply strings. + */ public String[] getEras() { return eras; } - + /** + * This method returns the pattern character information for this + * object. This is an 18 character string that contains the characters + * that are used in creating the date formatting strings in + * SimpleDateFormat. The following are the character + * positions in the string and which format character they correspond + * to (the character in parentheses is the default value in the US English + * locale): + *

+ *

    + *
  • 0 - era (G) + *
  • 1 - year (y) + *
  • 2 - month (M) + *
  • 4 - hour out of 12, from 1-12 (h) + *
  • 5 - hour out of 24, from 0-23 (H) + *
  • 6 - minute (m) + *
  • 7 - second (s) + *
  • 8 - millisecond (S) + *
  • 9 - date of week (E) + *
  • 10 - date of year (D) + *
  • 11 - day of week in month, eg. "4th Thur in Nov" (F) + *
  • 12 - week in year (w) + *
  • 13 - week in month (W) + *
  • 14 - am/pm (a) + *
  • 15 - hour out of 24, from 1-24 (k) + *
  • 16 - hour out of 12, from 0-11 (K) + *
  • 17 - time zone (z) + *
+ * + * @return The format patter characters + */ public String getLocalPatternChars() { return localPatternChars; } + /** + * This method returns the list of strings used for displaying month + * names (e.g., "January" and "February"). This is a thirteen element + * string array indexed by Calendar.JANUARY through + * Calendar.UNDECEMBER. Note that there are thirteen + * elements because some calendars have thriteen months. + * + * @return The list of month display strings. + */ public String[] getMonths () { return months; } + /** + * This method returns the list of strings used for displaying abbreviated + * month names (e.g., "Jan" and "Feb"). This is a thirteen element + * String array indexed by Calendar.JANUARY + * through Calendar.UNDECEMBER. Note that there are thirteen + * elements because some calendars have thirteen months. + * + * @return The list of abbreviated month display strings. + */ public String[] getShortMonths () { return shortMonths; } + /** + * This method returns the list of strings used for displaying abbreviated + * weekday names (e.g., "Sun" and "Mon"). This is an eight element + * String array indexed by Calendar.SUNDAY + * through Calendar.SATURDAY. Note that the first element + * of this array is ignored. + * + * @return This list of abbreviated weekday display strings. + */ public String[] getShortWeekdays () { return shortWeekdays; } + /** + * This method returns the list of strings used for displaying weekday + * names (e.g., "Sunday" and "Monday"). This is an eight element + * String array indexed by Calendar.SUNDAY + * through Calendar.SATURDAY. Note that the first element + * of this array is ignored. + * + * @return This list of weekday display strings. + */ public String[] getWeekdays () { return weekdays; } + /** + * This method returns this list of localized timezone display strings. + * This is a two dimensional String array where each row in + * the array contains five values: + *

+ *

    + *
  • 0 - The non-localized time zone id string. + *
  • 1 - The long name of the time zone (standard time). + *
  • 2 - The short name of the time zone (standard time). + *
  • 3 - The long name of the time zone (daylight savings time). + *
  • 4 - the short name of the time zone (daylight savings time). + * + * @return The list of time zone display strings. + */ public String[] [] getZoneStrings () { return zoneStrings; } + /** + * This method sets the list of strings used to display AM/PM values to + * the specified list. + * This is a two element String array indexed by + * Calendar.AM and Calendar.PM + * + * @param ampms The new list of AM/PM display strings. + */ public void setAmPmStrings (String[] value) { ampms = value; } + /** + * This method sets the list of strings used to display time eras to + * to the specified list. + * This is a two element String + * array indexed by Calendar.BC and Calendar.AD. + * + * @param eras The new list of era disply strings. + */ public void setEras (String[] value) { eras = value; } + /** + * This method sets the list of characters used to specific date/time + * formatting strings. + * This is an 18 character string that contains the characters + * that are used in creating the date formatting strings in + * SimpleDateFormat. The following are the character + * positions in the string and which format character they correspond + * to (the character in parentheses is the default value in the US English + * locale): + *

    + *

      + *
    • 0 - era (G) + *
    • 1 - year (y) + *
    • 2 - month (M) + *
    • 4 - hour out of 12, from 1-12 (h) + *
    • 5 - hour out of 24, from 0-23 (H) + *
    • 6 - minute (m) + *
    • 7 - second (s) + *
    • 8 - millisecond (S) + *
    • 9 - date of week (E) + *
    • 10 - date of year (D) + *
    • 11 - day of week in month, eg. "4th Thur in Nov" (F) + *
    • 12 - week in year (w) + *
    • 13 - week in month (W) + *
    • 14 - am/pm (a) + *
    • 15 - hour out of 24, from 1-24 (k) + *
    • 16 - hour out of 12, from 0-11 (K) + *
    • 17 - time zone (z) + *
    + * + * @param localPatternChars The new format patter characters + */ public void setLocalPatternChars (String value) { localPatternChars = value; } + /** + * This method sets the list of strings used to display month names. + * This is a thirteen element + * string array indexed by Calendar.JANUARY through + * Calendar.UNDECEMBER. Note that there are thirteen + * elements because some calendars have thriteen months. + * + * @param months The list of month display strings. + */ public void setMonths (String[] value) { months = value; } + /** + * This method sets the list of strings used to display abbreviated month + * names. + * This is a thirteen element + * String array indexed by Calendar.JANUARY + * through Calendar.UNDECEMBER. Note that there are thirteen + * elements because some calendars have thirteen months. + * + * @param shortMonths The new list of abbreviated month display strings. + */ public void setShortMonths (String[] value) { shortMonths = value; } + /** + * This method sets the list of strings used to display abbreviated + * weekday names. + * This is an eight element + * String array indexed by Calendar.SUNDAY + * through Calendar.SATURDAY. Note that the first element + * of this array is ignored. + * + * @param shortWeekdays This list of abbreviated weekday display strings. + */ public void setShortWeekdays (String[] value) { shortWeekdays = value; } + /** + * This method sets the list of strings used to display weekday names. + * This is an eight element + * String array indexed by Calendar.SUNDAY + * through Calendar.SATURDAY. Note that the first element + * of this array is ignored. + * + * @param weekdays This list of weekday display strings. + */ public void setWeekdays (String[] value) { weekdays = value; } + /** + * This method sets the list of display strings for time zones. + * This is a two dimensional String array where each row in + * the array contains five values: + *

    + *

      + *
    • 0 - The non-localized time zone id string. + *
    • 1 - The long name of the time zone (standard time). + *
    • 2 - The short name of the time zone (standard time). + *
    • 3 - The long name of the time zone (daylight savings time). + *
    • 4 - the short name of the time zone (daylight savings time). + * + * @return The list of time zone display strings. + */ public void setZoneStrings (String[][] value) { zoneStrings = value; @@ -292,9 +403,24 @@ public class DateFormatSymbols extends Object return hash; } + /** + * This method tests a specified object for equality against this object. + * This will be true if and only if the specified object: + *

      + *

        + *
      • Is not null. + *
      • Is an instance of DateFormatSymbols. + *
      • Contains identical formatting symbols to this object. + *
      + * + * @param obj The Object to test for equality against. + * + * @return true if the specified object is equal to this one, + * false otherwise. + */ public boolean equals (Object obj) { - if (obj == null || ! (obj instanceof DateFormatSymbols)) + if (! (obj instanceof DateFormatSymbols)) return false; DateFormatSymbols other = (DateFormatSymbols) obj; return (equals(ampms, other.ampms) @@ -307,11 +433,28 @@ public class DateFormatSymbols extends Object && equals(zoneStrings, other.zoneStrings)); } + /** + * Returns a new copy of this object. + * + * @param A copy of this object + */ public Object clone () { - return new DateFormatSymbols (this); + try + { + return super.clone (); + } + catch (CloneNotSupportedException e) + { + return null; + } } + /** + * This method returns a hash value for this object. + * + * @return A hash value for this object. + */ public int hashCode () { return (hashCode(ampms) diff --git a/libjava/java/text/DecimalFormat.java b/libjava/java/text/DecimalFormat.java index 42c81078cb2..f6b7223ed04 100644 --- a/libjava/java/text/DecimalFormat.java +++ b/libjava/java/text/DecimalFormat.java @@ -1,12 +1,28 @@ -// 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. */ +/* DecimalFormat.java -- Formats and parses numbers + Copyright (C) 1999, 2000, 2001 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ package java.text; @@ -26,7 +42,6 @@ import java.io.IOException; * 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 @@ -34,940 +49,940 @@ public class DecimalFormat extends NumberFormat 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 + { + 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; - } + ++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; - } + 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; + { + int max = pattern.length(); - ++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()) + 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()) - { - 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; - } + } + 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(); - } + { + 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); - } - } + { + // 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); - } + { + // 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); - } + { + // 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); - } + { + 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; - } + { + 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.###"); - } + { + this ("#,##0.###"); + } public DecimalFormat (String pattern) - { - this (pattern, new DecimalFormatSymbols ()); - } + { + this (pattern, new DecimalFormatSymbols ()); + } public DecimalFormat (String pattern, DecimalFormatSymbols symbols) - { - this.symbols = symbols; - applyPattern (pattern); - } + { + 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); - } + { + 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); - } + { + 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; - } + { + // 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; - } + { + // 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; - } + { + return symbols; + } public int getGroupingSize () - { - return groupingSize; - } + { + return groupingSize; + } public int getMultiplier () - { - return multiplier; - } + { + return multiplier; + } public String getNegativePrefix () - { - return negativePrefix; - } + { + return negativePrefix; + } public String getNegativeSuffix () - { - return negativeSuffix; - } + { + return negativeSuffix; + } public String getPositivePrefix () - { - return positivePrefix; - } + { + return positivePrefix; + } public String getPositiveSuffix () - { - return positiveSuffix; - } + { + return positiveSuffix; + } public int hashCode () - { - int hash = (negativeSuffix.hashCode() ^ negativePrefix.hashCode() - ^positivePrefix.hashCode() ^ positiveSuffix.hashCode()); - // FIXME. - return hash; - } + { + int hash = (negativeSuffix.hashCode() ^ negativePrefix.hashCode() + ^positivePrefix.hashCode() ^ positiveSuffix.hashCode()); + // FIXME. + return hash; + } public boolean isDecimalSeparatorAlwaysShown () - { - return decimalSeparatorAlwaysShown; - } + { + 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. + { + // 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 (); + 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. + 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; - } + 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; - } + { + symbols = newSymbols; + } public void setDecimalSeparatorAlwaysShown (boolean newValue) - { - decimalSeparatorAlwaysShown = newValue; - } + { + decimalSeparatorAlwaysShown = newValue; + } public void setGroupingSize (int groupSize) - { - groupingSize = (byte) groupSize; - } + { + groupingSize = (byte) groupSize; + } public void setMaximumFractionDigits (int newValue) - { - maximumFractionDigits = Math.min(newValue, 340); - } + { + maximumFractionDigits = Math.min(newValue, 340); + } public void setMaximumIntegerDigits (int newValue) - { - maximumIntegerDigits = Math.min(newValue, 309); - } + { + maximumIntegerDigits = Math.min(newValue, 309); + } public void setMinimumFractionDigits (int newValue) - { - minimumFractionDigits = Math.min(newValue, 340); - } + { + minimumFractionDigits = Math.min(newValue, 340); + } public void setMinimumIntegerDigits (int newValue) - { - minimumIntegerDigits = Math.min(newValue, 309); - } + { + minimumIntegerDigits = Math.min(newValue, 309); + } public void setMultiplier (int newValue) - { - multiplier = newValue; - } + { + multiplier = newValue; + } public void setNegativePrefix (String newValue) - { - negativePrefix = newValue; - } + { + negativePrefix = newValue; + } public void setNegativeSuffix (String newValue) - { - negativeSuffix = newValue; - } + { + negativeSuffix = newValue; + } public void setPositivePrefix (String newValue) - { - positivePrefix = newValue; - } + { + positivePrefix = newValue; + } public void setPositiveSuffix (String newValue) - { - positiveSuffix = 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 + { + 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(); - } + { + 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); - } + { + return computePattern (symbols); + } public String toPattern () - { - return computePattern (nonLocalizedSymbols); - } + { + return computePattern (nonLocalizedSymbols); + } // These names are fixed by the serialization spec. private boolean decimalSeparatorAlwaysShown; diff --git a/libjava/java/text/DecimalFormatSymbols.java b/libjava/java/text/DecimalFormatSymbols.java index 0f404a57235..bc5776a5668 100644 --- a/libjava/java/text/DecimalFormatSymbols.java +++ b/libjava/java/text/DecimalFormatSymbols.java @@ -1,12 +1,29 @@ -// DecimalFormatSymbols.java - Symbols used to format numbers. +/* DecimalFormatSymbols.java -- Format symbols used by DecimalFormat + Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. -/* Copyright (C) 1999, 2000 Free Software Foundation +This file is part of GNU Classpath. - This file is part of libgcj. +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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ package java.text; @@ -18,302 +35,524 @@ import java.io.ObjectInputStream; import java.io.IOException; /** + * This class is a container for the symbols used by + * DecimalFormat to format numbers and currency. These are + * normally handled automatically, but an application can override + * values as desired using this class. + * * @author Tom Tromey + * @author Aaron M. Renn (arenn@urbanophile.com) * @date February 24, 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. */ - public final class DecimalFormatSymbols implements Cloneable, Serializable { public Object clone () - { - return new DecimalFormatSymbols (this); - } - - private DecimalFormatSymbols (DecimalFormatSymbols orig) - { - this.currencySymbol = orig.currencySymbol; - this.decimalSeparator = orig.decimalSeparator; - this.digit = orig.digit; - this.exponential = orig.exponential; - this.groupingSeparator = orig.groupingSeparator; - this.infinity = orig.infinity; - this.intlCurrencySymbol = orig.intlCurrencySymbol; - this.monetarySeparator = orig.monetarySeparator; - this.minusSign = orig.minusSign; - this.NaN = orig.NaN; - this.patternSeparator = orig.patternSeparator; - this.percent = orig.percent; - this.perMill = orig.perMill; - this.zeroDigit = orig.zeroDigit; - } + { + try + { + return super.clone (); + } + catch(CloneNotSupportedException e) + { + return null; + } + } + /** + * This method initializes a new instance of + * DecimalFormatSymbols for the default locale. + */ public DecimalFormatSymbols () - { - this (Locale.getDefault()); - } + { + this (Locale.getDefault()); + } private final String safeGetString (ResourceBundle bundle, String name, String def) - { - if (bundle != null) - { - try - { - return bundle.getString(name); - } - catch (MissingResourceException x) - { - } - } - return def; - } + { + if (bundle != null) + { + try + { + return bundle.getString(name); + } + catch (MissingResourceException x) + { + } + } + return def; + } private final char safeGetChar (ResourceBundle bundle, String name, char def) - { - String r = null; - if (bundle != null) - { - try - { - r = bundle.getString(name); - } - catch (MissingResourceException x) - { - } - } - if (r == null || r.length() < 1) - return def; - return r.charAt(0); - } + { + String r = null; + if (bundle != null) + { + try + { + r = bundle.getString(name); + } + catch (MissingResourceException x) + { + } + } + if (r == null || r.length() < 1) + return def; + return r.charAt(0); + } + /** + * This method initializes a new instance of + * DecimalFormatSymbols for the specified locale. + * + * @param locale The local to load symbols for. + */ public DecimalFormatSymbols (Locale loc) - { - ResourceBundle res; - try - { - res = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", loc); - } - catch (MissingResourceException x) - { - res = null; - } - currencySymbol = safeGetString (res, "currencySymbol", "$"); - decimalSeparator = safeGetChar (res, "decimalSeparator", '.'); - digit = safeGetChar (res, "digit", '#'); - exponential = safeGetChar (res, "exponential", 'E'); - groupingSeparator = safeGetChar (res, "groupingSeparator", ','); - infinity = safeGetString (res, "infinity", "\u221e"); - // FIXME: default? - intlCurrencySymbol = safeGetString (res, "intlCurrencySymbol", "$"); - try - { - monetarySeparator = safeGetChar (res, "monetarySeparator", '.'); - } - catch (MissingResourceException x) - { - monetarySeparator = decimalSeparator; - } - minusSign = safeGetChar (res, "minusSign", '-'); - NaN = safeGetString (res, "NaN", "\ufffd"); - patternSeparator = safeGetChar (res, "patternSeparator", ';'); - percent = safeGetChar (res, "percent", '%'); - perMill = safeGetChar (res, "perMill", '\u2030'); - zeroDigit = safeGetChar (res, "zeroDigit", '0'); - } + { + ResourceBundle res; + try + { + res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", + loc); + } + catch (MissingResourceException x) + { + res = null; + } + currencySymbol = safeGetString (res, "currencySymbol", "$"); + decimalSeparator = safeGetChar (res, "decimalSeparator", '.'); + digit = safeGetChar (res, "digit", '#'); + exponential = safeGetChar (res, "exponential", 'E'); + groupingSeparator = safeGetChar (res, "groupingSeparator", ','); + infinity = safeGetString (res, "infinity", "\u221e"); + // FIXME: default? + intlCurrencySymbol = safeGetString (res, "intlCurrencySymbol", "$"); + try + { + monetarySeparator = safeGetChar (res, "monetarySeparator", '.'); + } + catch (MissingResourceException x) + { + monetarySeparator = decimalSeparator; + } + minusSign = safeGetChar (res, "minusSign", '-'); + NaN = safeGetString (res, "NaN", "\ufffd"); + patternSeparator = safeGetChar (res, "patternSeparator", ';'); + percent = safeGetChar (res, "percent", '%'); + perMill = safeGetChar (res, "perMill", '\u2030'); + zeroDigit = safeGetChar (res, "zeroDigit", '0'); + } + /** + * This method this this object for equality against the specified object. + * This will be true if and only if the following criteria are met with + * regard to the specified object: + *

      + *

        + *
      • It is not null. + *
      • It is an instance of DecimalFormatSymbols + *
      • All of its symbols are identical to the symbols in this object. + *
      + * + * @return true if the specified object is equal to this + * object, false otherwise. + */ public boolean equals (Object obj) - { - if (! (obj instanceof DecimalFormatSymbols)) - return false; - DecimalFormatSymbols dfs = (DecimalFormatSymbols) obj; - return (currencySymbol.equals(dfs.currencySymbol) - && decimalSeparator == dfs.decimalSeparator - && digit == dfs.digit - && exponential == dfs.exponential - && groupingSeparator == dfs.groupingSeparator - && infinity.equals(dfs.infinity) - && intlCurrencySymbol.equals(dfs.intlCurrencySymbol) - && minusSign == dfs.minusSign - && monetarySeparator == dfs.monetarySeparator - && NaN.equals(dfs.NaN) - && patternSeparator == dfs.patternSeparator - && percent == dfs.percent - && perMill == dfs.perMill - && zeroDigit == dfs.zeroDigit); - } + { + if (! (obj instanceof DecimalFormatSymbols)) + return false; + DecimalFormatSymbols dfs = (DecimalFormatSymbols) obj; + return (currencySymbol.equals(dfs.currencySymbol) + && decimalSeparator == dfs.decimalSeparator + && digit == dfs.digit + && exponential == dfs.exponential + && groupingSeparator == dfs.groupingSeparator + && infinity.equals(dfs.infinity) + && intlCurrencySymbol.equals(dfs.intlCurrencySymbol) + && minusSign == dfs.minusSign + && monetarySeparator == dfs.monetarySeparator + && NaN.equals(dfs.NaN) + && patternSeparator == dfs.patternSeparator + && percent == dfs.percent + && perMill == dfs.perMill + && zeroDigit == dfs.zeroDigit); + } + /** + * This method returns the currency symbol in local format. For example, + * "$" for Canadian dollars. + * + * @return The currency symbol in local format. + */ public String getCurrencySymbol () - { - return currencySymbol; - } + { + return currencySymbol; + } + /** + * This method returns the character used as the decimal point. + * + * @return The character used as the decimal point. + */ public char getDecimalSeparator () - { - return decimalSeparator; - } + { + return decimalSeparator; + } + /** + * This method returns the character used to represent a digit in a + * format pattern string. + * + * @return The character used to represent a digit in a format + * pattern string. + */ public char getDigit () - { - return digit; - } + { + return digit; + } // This is our own extension. char getExponential () - { - return exponential; - } + { + return exponential; + } + /** + * This method sets the character used to separate groups of digits. For + * example, the United States uses a comma (,) to separate thousands in + * a number. + * + * @return The character used to separate groups of digits. + */ public char getGroupingSeparator () - { - return groupingSeparator; - } + { + return groupingSeparator; + } + /** + * This method returns the character used to represent infinity. + * + * @return The character used to represent infinity. + */ public String getInfinity () - { - return infinity; - } + { + return infinity; + } + /** + * This method returns the currency symbol in international format. For + * example, "C$" for Canadian dollars. + * + * @return The currency symbol in international format. + */ public String getInternationalCurrencySymbol () - { - return intlCurrencySymbol; - } + { + return intlCurrencySymbol; + } + /** + * This method returns the character used to represent the minus sign. + * + * @return The character used to represent the minus sign. + */ public char getMinusSign () - { - return minusSign; - } + { + return minusSign; + } + /** + * This method returns the character used to represent the decimal + * point for currency values. + * + * @return The decimal point character used in currency values. + */ public char getMonetaryDecimalSeparator () - { - return monetarySeparator; - } + { + return monetarySeparator; + } + /** + * This method returns the string used to represent the NaN (not a number) + * value. + * + * @return The string used to represent NaN + */ public String getNaN () - { - return NaN; - } + { + return NaN; + } + /** + * This method returns the character used to separate positive and negative + * subpatterns in a format pattern. + * + * @return The character used to separate positive and negative subpatterns + * in a format pattern. + */ public char getPatternSeparator () - { - return patternSeparator; - } + { + return patternSeparator; + } + /** + * This method returns the character used as the percent sign. + * + * @return The character used as the percent sign. + */ public char getPercent () - { - return percent; - } + { + return percent; + } + /** + * This method returns the character used as the per mille character. + * + * @return The per mille character. + */ public char getPerMill () - { - return perMill; - } + { + return perMill; + } + /** + * This method returns the character used to represent the digit zero. + * + * @return The character used to represent the digit zero. + */ public char getZeroDigit () - { - return zeroDigit; - } + { + return zeroDigit; + } + /** + * This method returns a hash value for this object. + * + * @return A hash value for this object. + */ public int hashCode () - { - // Compute based on zero digit, grouping separator, and decimal - // separator -- JCL book. This probably isn't a very good hash - // code. - return zeroDigit << 16 + groupingSeparator << 8 + decimalSeparator; - } + { + // Compute based on zero digit, grouping separator, and decimal + // separator -- JCL book. This probably isn't a very good hash + // code. + return zeroDigit << 16 + groupingSeparator << 8 + decimalSeparator; + } + /** + * This method sets the currency symbol to the specified value. + * + * @param currencySymbol The new currency symbol + */ public void setCurrencySymbol (String currency) - { - currencySymbol = currency; - } + { + currencySymbol = currency; + } + /** + * This method sets the decimal point character to the specified value. + * + * @param decimalSeparator The new decimal point character + */ public void setDecimalSeparator (char decimalSep) - { - decimalSeparator = decimalSep; - } + { + decimalSeparator = decimalSep; + } + /** + * This method sets the character used to represents a digit in a format + * string to the specified value. + * + * @param digit The character used to represent a digit in a format pattern. + */ public void setDigit (char digit) - { - this.digit = digit; - } + { + this.digit = digit; + } // This is our own extension. void setExponential (char exp) - { - exponential = exp; - } + { + exponential = exp; + } + /** + * This method sets the character used to separate groups of digits. + * + * @param groupingSeparator The character used to separate groups of digits. + */ public void setGroupingSeparator (char groupSep) - { - groupingSeparator = groupSep; - } + { + groupingSeparator = groupSep; + } + /** + * This method sets the string used to represents infinity. + * + * @param infinity The string used to represent infinity. + */ public void setInfinity (String infinity) - { - this.infinity = infinity; - } + { + this.infinity = infinity; + } + /** + * This method sets the international currency symbols to the + * specified value. + * + * @param intlCurrencySymbol The new international currency symbol. + */ public void setInternationalCurrencySymbol (String currency) - { - intlCurrencySymbol = currency; - } + { + intlCurrencySymbol = currency; + } + /** + * This method sets the character used to represent the minus sign. + * + * @param minusSign The character used to represent the minus sign. + */ public void setMinusSign (char minusSign) - { - this.minusSign = minusSign; - } + { + this.minusSign = minusSign; + } + /** + * This method sets the character used for the decimal point in currency + * values. + * + * @param monetarySeparator The decimal point character used in + * currency values. + */ public void setMonetaryDecimalSeparator (char decimalSep) - { - monetarySeparator = decimalSep; - } + { + monetarySeparator = decimalSep; + } + /** + * This method sets the string used to represent the NaN (not a + * number) value. + * + * @param NaN The string used to represent NaN + */ public void setNaN (String nan) - { - NaN = nan; - } + { + NaN = nan; + } + /** + * This method sets the character used to separate positive and negative + * subpatterns in a format pattern. + * + * @param patternSeparator The character used to separate positive and + * negative subpatterns in a format pattern. + */ public void setPatternSeparator (char patternSep) - { - patternSeparator = patternSep; - } + { + patternSeparator = patternSep; + } + /** + * This method sets the character used as the percent sign. + * + * @param percent The character used as the percent sign. + */ public void setPercent (char percent) - { - this.percent = percent; - } + { + this.percent = percent; + } + /** + * This method sets the character used as the per mille character. + * + * @param perMill The per mille character. + */ public void setPerMill (char perMill) - { - this.perMill = perMill; - } + { + this.perMill = perMill; + } + /** + * This method sets the charcter used to represen the digit zero. + * + * @param zeroDigit The character used to represent the digit zero. + */ public void setZeroDigit (char zeroDigit) - { - this.zeroDigit = zeroDigit; - } + { + this.zeroDigit = zeroDigit; + } - // The names of the instance variables are fixed by the - // serialization spec. + /** + * @serial A string used for the local currency + */ private String currencySymbol; + /** + * @serial The char used to separate decimals in a number. + */ private char decimalSeparator; + /** + * @serial This is the char used to represent a digit in + * a format specification. + */ private char digit; + /** + * @serial This is the char used to represent the exponent + * separator in exponential notation. + */ private char exponential; + /** + * @serial This separates groups of thousands in numbers. + */ private char groupingSeparator; + /** + * @serial This string represents infinity. + */ private String infinity; + /** + * @serial This string represents the local currency in an international + * context, eg, "C$" for Canadian dollars. + */ private String intlCurrencySymbol; + /** + * @serial This is the character used to represent the minus sign. + */ private char minusSign; + /** + * @serial This character is used to separate decimals when formatting + * currency values. + */ private char monetarySeparator; + /** + * @serial This string is used the represent the Java NaN value for + * "not a number". + */ private String NaN; + /** + * @serial This is the character used to separate positive and negative + * subpatterns in a format pattern. + */ private char patternSeparator; + /** + * @serial This is the percent symbols + */ private char percent; + /** + * @serial This character is used for the mille percent sign. + */ private char perMill; + /** + * @serial This value represents the type of object being de-serialized. + * 0 indicates a pre-Java 1.1.6 version, 1 indicates 1.1.6 or later. + */ private int serialVersionOnStream = 1; + /** + * @serial This is the character used to represent 0. + */ private char zeroDigit; + private static final long serialVersionUID = 5772796243397350300L; private void readObject(ObjectInputStream stream) diff --git a/libjava/java/text/FieldPosition.java b/libjava/java/text/FieldPosition.java index c149e0eabb6..57ede5b69d4 100644 --- a/libjava/java/text/FieldPosition.java +++ b/libjava/java/text/FieldPosition.java @@ -1,65 +1,155 @@ -/* Copyright (C) 1998, 1999 Free Software Foundation +/* FieldPosition.java -- Keeps track of field positions while formatting + Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. - This file is part of libgcj. +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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ package java.text; /** + * This class is used by the java.text formatting classes to track + * field positions. A field position is defined by an identifier value + * and begin and end index positions. The formatting classes in java.text + * typically define constant values for the field identifiers. + * + * @author Aaron M. Renn (arenn@urbanophile.com) * @author Per Bothner - * @date October 25, 1998. - */ -/* Written using "Java Class Libraries", 2nd edition, plus online - * API docs for JDK 1.2 beta from http://www.javasoft.com. - * Status: Believed complete and correct. - * Includes JDK 1.2 methods. */ - public class FieldPosition { - int field; - int beginIndex; - int endIndex; + /** + * This is the field identifier value. + */ + private int field_id; + + /** + * This is the beginning index of the field. + */ + private int begin; + + /** + * This is the ending index of the field. + */ + private int end; - public FieldPosition (int field) + /** + * This method initializes a new instance of FieldPosition to + * have the specified field id. + * + * @param field_id The field identifier value. + */ + public FieldPosition (int field_id) { - this.field = field; + this.field_id = field_id; } + /** + * This method returns the field identifier value for this object. + * + * @return The field identifier. + */ public int getField () { - return field; + return field_id; } + /** + * This method returns the beginning index for this field. + * + * @return The beginning index. + */ public int getBeginIndex () { - return beginIndex; + return begin; } - public int getEndIndex () + /** + * This method sets the beginning index of this field to the specified value. + * + * @param begin The new beginning index. + */ + public void setBeginIndex (int begin) { - return endIndex; + this.begin = begin; } - public void setBeginIndex (int index) + /** + * This method returns the ending index for the field. + * + * @return The ending index. + */ + public int getEndIndex () { - beginIndex = index; + return end; } - public void setEndIndex (int index) + /** + * This method sets the ending index of this field to the specified value. + * + * @param end The new ending index. + */ + public void setEndIndex (int end) { - endIndex = index; + this.end = end; } + /** + * This method tests this object for equality against the specified object. + * The objects will be considered equal if and only if: + *

      + *

        + *
      • The specified object is not null. + *
      • The specified object is an instance of FieldPosition. + *
      • The specified object has the same field identifier and beginning + * and ending index as this object. + *
      + * + * @param obj The object to test for equality to this object. + * + * @return true if the specified object is equal to + * this object, false otherwise. + */ public boolean equals (Object obj) { if (! (obj instanceof FieldPosition)) return false; - FieldPosition other = (FieldPosition) obj; - return (field == other.field - && beginIndex == other.beginIndex && endIndex == other.endIndex); + + FieldPosition fp = (FieldPosition) obj; + return (field_id == fp.field_id + && begin == fp.begin + && end == fp.end); + } + + /** + * This method returns a String representation of this + * object. + * + * @return A String representation of this object. + */ + public String toString () + { + return (getClass ().getName () + "[field=" + getField () + ",beginIndex=" + + getBeginIndex () + ",endIndex=" + getEndIndex () + "]"); } } diff --git a/libjava/java/text/Format.java b/libjava/java/text/Format.java index 8360415729b..3aa68c8f3e1 100644 --- a/libjava/java/text/Format.java +++ b/libjava/java/text/Format.java @@ -1,44 +1,111 @@ -/* Copyright (C) 1998, 1999, 2000 Free Software Foundation +/* Format.java -- Abstract superclass for formatting/parsing strings. + Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - This file is part of libgcj. +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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -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.io.Serializable; + /** + * This class is the abstract superclass of classes that format and parse + * data to/from Strings. It is guaranteed that any + * String produced by a concrete subclass of Format + * will be parseable by that same subclass. + *

      + * In addition to implementing the abstract methods in this class, subclasses + * should provide static factory methods of the form + * getInstance() and getInstance(Locale) if the + * subclass loads different formatting/parsing schemes based on locale. + * These subclasses should also implement a static method called + * getAvailableLocales() which returns an array of + * available locales in the current runtime environment. + * + * @author Aaron M. Renn (arenn@urbanophile.com) * @author Per Bothner - * @date October 25, 1998. - */ -/* Written using "Java Class Libraries", 2nd edition, plus online - * API docs for JDK 1.2 beta from http://www.javasoft.com. - * Status: Believed complete and correct. */ - -public abstract class Format implements java.io.Serializable, Cloneable +public abstract class Format implements Serializable, Cloneable { + /** + * This method initializes a new instance of Format. + * It performs no actions, but acts as a default constructor for + * subclasses. + */ public Format () { } - public abstract StringBuffer format (Object obj, - StringBuffer sbuf, FieldPosition pos); - - public final String format (Object obj) + /** + * This method formats an Object into a String. + * + * @param obj The Object to format. + * + * @return The formatted String. + * + * @exception IllegalArgumentException If the Object + * cannot be formatted. + */ + public final String format(Object obj) throws IllegalArgumentException { - StringBuffer sbuf = new StringBuffer(); - format(obj, sbuf, new FieldPosition(0)); - return sbuf.toString(); + StringBuffer sb = new StringBuffer (); + format (obj, sb, new FieldPosition (0)); + return sb.toString (); } - public abstract Object parseObject (String source, ParsePosition pos); + /** + * This method formats an Object into a String and + * appends the String to a StringBuffer. + * + * @param obj The Object to format. + * @param sb The StringBuffer to append to. + * @param pos The desired FieldPosition, which is also + * updated by this call. + * + * @return The updated StringBuffer. + * + * @exception IllegalArgumentException If the Object + * cannot be formatted. + */ + public abstract StringBuffer format (Object obj, StringBuffer sb, + FieldPosition pos) + throws IllegalArgumentException; - public Object parseObject (String source) throws ParseException + /** + * This method parses a String and converts the parsed + * contents into an Object. + * + * @param str The String to parse. + * + * @return The resulting Object. + * + * @exception ParseException If the String cannot be parsed. + */ + public Object parseObject (String str) throws ParseException { ParsePosition pos = new ParsePosition(0); - Object result = parseObject (source, pos); + Object result = parseObject (str, pos); if (result == null) { int index = pos.getErrorIndex(); @@ -49,8 +116,33 @@ public abstract class Format implements java.io.Serializable, Cloneable return result; } + /** + * This method parses a String and converts the parsed + * contents into an Object. + * + * @param str The String to parse. + * @param pos The starting parse index on input, the ending parse + * index on output. + * + * @return The parsed Object, or null in + * case of error. + */ + public abstract Object parseObject (String str, ParsePosition pos); + + /** + * Creates a copy of this object. + * + * @return The copied Object. + */ public Object clone () { - return super.clone (); + try + { + return super.clone (); + } + catch (CloneNotSupportedException e) + { + return null; + } } } diff --git a/libjava/java/text/MessageFormat.java b/libjava/java/text/MessageFormat.java index bb2a4c3592a..ffe34a68a2f 100644 --- a/libjava/java/text/MessageFormat.java +++ b/libjava/java/text/MessageFormat.java @@ -1,12 +1,29 @@ -// MessageFormat.java - Localized message formatting. +/* MessageFormat.java - Localized message formatting. + Copyright (C) 1999, 2001 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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -/* Copyright (C) 1999, 2001 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; diff --git a/libjava/java/text/NumberFormat.java b/libjava/java/text/NumberFormat.java index 80d5c136255..739ca31538e 100644 --- a/libjava/java/text/NumberFormat.java +++ b/libjava/java/text/NumberFormat.java @@ -1,10 +1,29 @@ -/* Copyright (C) 1998, 1999, 2000 Free Software Foundation +/* NumberFormat.java -- Formats and parses numbers + Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. - This file is part of libgcj. +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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ package java.text; @@ -16,50 +35,108 @@ import java.io.ObjectOutputStream; import java.io.IOException; /** + * This is the abstract superclass of all classes which format and + * parse numeric values such as decimal numbers, integers, currency values, + * and percentages. These classes perform their parsing and formatting + * in a locale specific manner, accounting for such items as differing + * currency symbols and thousands separators. + *

      + * To create an instance of a concrete subclass of NumberFormat, + * do not call a class constructor directly. Instead, use one of the + * static factory methods in this class such as + * getCurrencyInstance. + * * @author Tom Tromey + * @author Aaron M. Renn (arenn@urbanophile.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, except getAvailableLocales. */ - public abstract class NumberFormat extends Format implements Cloneable { + /** + * This is a constant used to create a FieldPosition object + * that will return the integer portion of a formatted number. + */ public static final int INTEGER_FIELD = 0; + + /** + * This is a constant used to create a FieldPosition object + * that will return the fractional portion of a formatted number. + */ public static final int FRACTION_FIELD = 1; + /** + * This method is a specialization of the format method that performs + * a simple formatting of the specified long number. + * + * @param number The long to format. + * + * @return The formatted number + */ public final String format (long number) - { - StringBuffer sbuf = new StringBuffer(50); - format (number, sbuf, null); - return sbuf.toString(); - } + { + StringBuffer sbuf = new StringBuffer(50); + format (number, sbuf, null); + return sbuf.toString(); + } public final StringBuffer format (Object obj, StringBuffer sbuf, FieldPosition pos) - { - if (obj instanceof Number) - return format(((Number) obj).doubleValue(), sbuf, pos); - else - throw new IllegalArgumentException - ("Cannot format given Object as a Number"); - } + { + if (obj instanceof Number) + return format(((Number) obj).doubleValue(), sbuf, pos); + else + throw new IllegalArgumentException + ("Cannot format given Object as a Number"); + } + /** + * This method formats the specified double and appends it to + * a StringBuffer. + * + * @param number The double to format. + * @param sb The StringBuffer to append the formatted number to. + * @param pos The desired FieldPosition. + * + * @return The StringBuffer with the appended number. + */ public abstract StringBuffer format (double number, StringBuffer sbuf, FieldPosition pos); + /** + * This method formats the specified long and appends it to + * a StringBuffer. + * + * @param number The long to format. + * @param sb The StringBuffer to append the formatted number to. + * @param pos The desired FieldPosition. + * + * @return The StringBuffer with the appended number. + */ public abstract StringBuffer format (long number, StringBuffer sbuf, FieldPosition pos); - public Object clone () - { - // We know the superclass just uses Object's generic cloner. - // Why not just inherit? Because the online docs specify that - // this method exists for this class. - return super.clone (); - } - + /** + * This method tests the specified object for equality against this object. + * This will be true if the following conditions are met: + *

      + *

        + *
      • The specified object is not null. + *
      • The specified object is an instance of NumberFormat. + *
      + *

      + * Since this method does not test much, it is highly advised that + * concrete subclasses override this method. + * + * @param obj The Object to test against equality with + * this object. + * + * @return true if the specified object is equal to + * this object, false otherwise. + */ public boolean equals (Object obj) { if (! (obj instanceof NumberFormat)) @@ -73,182 +150,406 @@ public abstract class NumberFormat extends Format implements Cloneable && parseIntegerOnly == nf.parseIntegerOnly); } + /** + * This method returns a list of locales for which concrete instances + * of NumberFormat subclasses may be created. + * + * @return The list of available locales. + */ public static Locale[] getAvailableLocales () - { - // FIXME. - return null; - } + { + Locale[] list = new Locale[1]; + list[0] = Locale.US; + return list; + } private static final NumberFormat computeInstance (Locale loc, String resource, String def) - { - ResourceBundle res; - try - { - res = ResourceBundle.getBundle("gnu.gcj.text.LocaleData", loc); - } - catch (MissingResourceException x) - { - res = null; - } - String fmt; - try - { - fmt = res == null ? def : res.getString(resource); - } - catch (MissingResourceException x) - { - fmt = def; - } - DecimalFormatSymbols dfs = new DecimalFormatSymbols (loc); - return new DecimalFormat (fmt, dfs); - } + { + ResourceBundle res; + try + { + res = ResourceBundle.getBundle("gnu.java.locale.LocaleInformation", + loc); + } + catch (MissingResourceException x) + { + res = null; + } + String fmt; + try + { + fmt = res == null ? def : res.getString(resource); + } + catch (MissingResourceException x) + { + fmt = def; + } + DecimalFormatSymbols dfs = new DecimalFormatSymbols (loc); + return new DecimalFormat (fmt, dfs); + } + /** + * This method returns an instance of NumberFormat suitable + * for formatting and parsing currency values in the default locale. + * + * @return An instance of NumberFormat for handling currencies. + */ public static final NumberFormat getCurrencyInstance () - { - return getCurrencyInstance (Locale.getDefault()); - } + { + return getCurrencyInstance (Locale.getDefault()); + } + /** + * This method returns an instance of NumberFormat suitable + * for formatting and parsing currency values in the specified locale. + * + * @return An instance of NumberFormat for handling currencies. + */ public static NumberFormat getCurrencyInstance (Locale loc) - { - return computeInstance (loc, "currencyFormat", "$#,##0.00;($#,##0.00)"); - } + { + return computeInstance (loc, "currencyFormat", "$#,##0.00;($#,##0.00)"); + } + /** + * This method returns a default instance for the default locale. This + * will be a concrete subclass of NumberFormat, but the + * actual class returned is dependent on the locale. + * + * @return An instance of the default NumberFormat class. + */ public static final NumberFormat getInstance () - { - return getInstance (Locale.getDefault()); - } + { + return getInstance (Locale.getDefault()); + } + /** + * This method returns a default instance for the specified locale. This + * will be a concrete subclass of NumberFormat, but the + * actual class returned is dependent on the locale. + * + * @param locale The desired locale. + * + * @return An instance of the default NumberFormat class. + */ public static NumberFormat getInstance (Locale loc) - { - // For now always return a number instance. - return getNumberInstance (loc); - } + { + // For now always return a number instance. + return getNumberInstance (loc); + } + /** + * This method returns the maximum number of digits allowed in the fraction + * portion of a number. + * + * @return The maximum number of digits allowed in the fraction + * portion of a number. + */ public int getMaximumFractionDigits () - { - return maximumFractionDigits; - } + { + return maximumFractionDigits; + } + /** + * This method returns the maximum number of digits allowed in the integer + * portion of a number. + * + * @return The maximum number of digits allowed in the integer + * portion of a number. + */ public int getMaximumIntegerDigits () - { - return maximumIntegerDigits; - } + { + return maximumIntegerDigits; + } + /** + * This method returns the minimum number of digits allowed in the fraction + * portion of a number. + * + * @return The minimum number of digits allowed in the fraction + * portion of a number. + */ public int getMinimumFractionDigits () - { - return minimumFractionDigits; - } + { + return minimumFractionDigits; + } + /** + * This method returns the minimum number of digits allowed in the integer + * portion of a number. + * + * @return The minimum number of digits allowed in the integer + * portion of a number. + */ public int getMinimumIntegerDigits () - { - return minimumIntegerDigits; - } + { + return minimumIntegerDigits; + } + /** + * This method returns a default instance for the specified locale. This + * will be a concrete subclass of NumberFormat, but the + * actual class returned is dependent on the locale. + * + * @param locale The desired locale. + * + * @return An instance of the default NumberFormat class. + */ public static final NumberFormat getNumberInstance () - { - return getNumberInstance (Locale.getDefault()); - } + { + return getNumberInstance (Locale.getDefault()); + } + /** + * This method returns a general purpose number formatting and parsing + * class for the default locale. This will be a concrete subclass of + * NumberFormat, but the actual class returned is dependent + * on the locale. + * + * @return An instance of a generic number formatter for the default locale. + */ public static NumberFormat getNumberInstance (Locale loc) - { - return computeInstance (loc, "numberFormat", "#,##0.###"); - } + { + return computeInstance (loc, "numberFormat", "#,##0.###"); + } + /** + * This method returns an instance of NumberFormat suitable + * for formatting and parsing percentage values in the default locale. + * + * @return An instance of NumberFormat for handling percentages. + */ public static final NumberFormat getPercentInstance () - { - return getPercentInstance (Locale.getDefault()); - } + { + return getPercentInstance (Locale.getDefault()); + } + /** + * This method returns an instance of NumberFormat suitable + * for formatting and parsing percentage values in the specified locale. + * + * @param locale The desired locale. + * + * @return An instance of NumberFormat for handling percentages. + */ public static NumberFormat getPercentInstance (Locale loc) - { - return computeInstance (loc, "percentFormat", "#,##0%"); - } + { + return computeInstance (loc, "percentFormat", "#,##0%"); + } + /** + * This method returns a hash value for this object. + * + * @return The hash code. + */ public int hashCode () - { - int hash = super.hashCode(); - hash ^= (maximumFractionDigits + maximumIntegerDigits - + minimumFractionDigits + minimumIntegerDigits); - if (groupingUsed) - hash ^= 0xf0f0; - if (parseIntegerOnly) - hash ^= 0x0f0f; - return hash; - } + { + int hash = super.hashCode(); + hash ^= (maximumFractionDigits + maximumIntegerDigits + + minimumFractionDigits + minimumIntegerDigits); + if (groupingUsed) + hash ^= 0xf0f0; + if (parseIntegerOnly) + hash ^= 0x0f0f; + return hash; + } + /** + * This method tests whether or not grouping is in use. Grouping is + * a method of marking separations in numbers, such as thousand separators + * in the US English locale. The grouping positions and symbols are all + * locale specific. As an example, with grouping disabled, the number one + * million would appear as "1000000". With grouping enabled, this number + * might appear as "1,000,000". (Both of these assume the US English + * locale). + * + * @return true if grouping is enabled, + * false otherwise. + */ public boolean isGroupingUsed () - { - return groupingUsed; - } + { + return groupingUsed; + } + /** + * This method tests whether or not only integer values should be parsed. + * If this class is parsing only integers, parsing stops at the decimal + * point. + * + * @return true if only integers are parsed, + * false otherwise. + */ public boolean isParseIntegerOnly () - { - return parseIntegerOnly; - } + { + return parseIntegerOnly; + } + /** + * This is a default constructor for use by subclasses. + */ public NumberFormat () - { - } + { + } + /** + * This method parses the specified string into a Number. This + * will be a Long if possible, otherwise it will be a + * Double. If no number can be parsed, no exception is + * thrown. Instead, the parse position remains at its initial index. + * + * @param str The string to parse. + * @param pp The desired ParsePosition. + * + * @return The parsed Number + */ public abstract Number parse (String sourceStr, ParsePosition pos); + /** + * This method parses the specified string into a Number. This + * will be a Long if possible, otherwise it will be a + * Double. If no number can be parsed, an exception will be + * thrown. + * + * @param str The string to parse. + * + * @return The parsed Number + * + * @exception ParseException If no number can be parsed. + */ public Number parse (String sourceStr) throws ParseException - { - ParsePosition pp = new ParsePosition (0); - Number r = parse (sourceStr, pp); - if (r == null) - { - int index = pp.getErrorIndex(); - if (index < 0) - index = pp.getIndex(); - throw new ParseException ("couldn't parse number", index); - } - return r; - } + { + ParsePosition pp = new ParsePosition (0); + Number r = parse (sourceStr, pp); + if (r == null) + { + int index = pp.getErrorIndex(); + if (index < 0) + index = pp.getIndex(); + throw new ParseException ("couldn't parse number", index); + } + return r; + } + /** + * This method parses the specified string into an Object. This + * will be a Long if possible, otherwise it will be a + * Double. If no number can be parsed, no exception is + * thrown. Instead, the parse position remains at its initial index. + * + * @param str The string to parse. + * @param pp The desired ParsePosition. + * + * @return The parsed Object + */ public final Object parseObject (String sourceStr, ParsePosition pos) - { - return parse (sourceStr, pos); - } + { + return parse (sourceStr, pos); + } + /** + * This method sets the grouping behavior of this formatter. Grouping is + * a method of marking separations in numbers, such as thousand separators + * in the US English locale. The grouping positions and symbols are all + * locale specific. As an example, with grouping disabled, the number one + * million would appear as "1000000". With grouping enabled, this number + * might appear as "1,000,000". (Both of these assume the US English + * locale). + * + * @param groupingUsed true to enable grouping, + * false to disable it. + */ public void setGroupingUsed (boolean newValue) - { - groupingUsed = newValue; - } + { + groupingUsed = newValue; + } + /** + * This method sets the maximum number of digits allowed in the fraction + * portion of a number to the specified value. If this is less than the + * current minimum allowed digits, the minimum allowed digits value will + * be lowered to be equal to the new maximum allowed digits value. + * + * @param maximumFractionDigits The new maximum fraction digits value. + */ public void setMaximumFractionDigits (int newValue) - { - maximumFractionDigits = newValue; - } + { + maximumFractionDigits = newValue; + if (getMinimumFractionDigits () > maximumFractionDigits) + setMinimumFractionDigits (maximumFractionDigits); + } + /** + * This method sets the maximum number of digits allowed in the integer + * portion of a number to the specified value. If this is less than the + * current minimum allowed digits, the minimum allowed digits value will + * be lowered to be equal to the new maximum allowed digits value. + * + * @param maximumIntegerDigits The new maximum integer digits value. + */ public void setMaximumIntegerDigits (int newValue) - { - maximumIntegerDigits = newValue; - } + { + maximumIntegerDigits = newValue; + if (getMinimumIntegerDigits () > maximumIntegerDigits) + setMinimumIntegerDigits (maximumIntegerDigits); + } + /** + * This method sets the minimum number of digits allowed in the fraction + * portion of a number to the specified value. If this is greater than the + * current maximum allowed digits, the maximum allowed digits value will + * be raised to be equal to the new minimum allowed digits value. + * + * @param minimumFractionDigits The new minimum fraction digits value. + */ public void setMinimumFractionDigits (int newValue) - { - minimumFractionDigits = newValue; - } + { + minimumFractionDigits = newValue; + if (getMaximumFractionDigits () < minimumFractionDigits) + setMaximumFractionDigits (minimumFractionDigits); + } + /** + * This method sets the minimum number of digits allowed in the integer + * portion of a number to the specified value. If this is greater than the + * current maximum allowed digits, the maximum allowed digits value will + * be raised to be equal to the new minimum allowed digits value. + * + * @param minimumIntegerDigits The new minimum integer digits value. + */ public void setMinimumIntegerDigits (int newValue) - { - minimumIntegerDigits = newValue; - } + { + minimumIntegerDigits = newValue; + if (getMaximumIntegerDigits () < minimumIntegerDigits) + setMaximumIntegerDigits (minimumIntegerDigits); + } + /** + * This method sets the parsing behavior of this object to parse only + * integers or not. + * + * @param parseIntegerOnly true to parse only integers, + * false otherwise. + */ public void setParseIntegerOnly (boolean value) - { - parseIntegerOnly = value; - } + { + parseIntegerOnly = value; + } + /** + * This method is a specialization of the format method that performs + * a simple formatting of the specified double number. + * + * @param number The double to format. + * + * @return The formatted number + */ public final String format (double number) - { - StringBuffer sbuf = new StringBuffer(50); - format (number, sbuf, null); - return sbuf.toString(); - } + { + StringBuffer sbuf = new StringBuffer(50); + format (number, sbuf, null); + return sbuf.toString(); + } // These field names are fixed by the serialization spec. boolean groupingUsed; diff --git a/libjava/java/text/ParsePosition.java b/libjava/java/text/ParsePosition.java index 55f7f8bb123..765ac4d532f 100644 --- a/libjava/java/text/ParsePosition.java +++ b/libjava/java/text/ParsePosition.java @@ -1,59 +1,140 @@ -/* Copyright (C) 1998, 1999 Free Software Foundation +/* ParsePosition.java -- Keep track of position while parsing. + Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. - This file is part of libgcj. +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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ package java.text; /** + * This class is used to keep track of the current position during parsing + * operations. + * + * @author Aaron M. Renn (arenn@urbanophile.com) * @author Per Bothner - * @date October 25, 1998. */ -/* Written using "Java Class Libraries", 2nd edition, plus online - * API docs for JDK 1.2 beta from http://www.javasoft.com. - * Status: Believed complete and correct. - * Includes JDK 1.2 methods. - */ - public class ParsePosition { - int index; - int errorIndex; + /** + * This is the index of the current parse position. + */ + private int index; + /** + * This is the index of the position where an error occurred during parsing. + */ + private int error_index; + + /** + * This method initializes a new instance of ParsePosition to + * have the specified initial index value. + * + * @param index The initial parsing index. + */ public ParsePosition (int index) { this.index = index; - errorIndex = -1; + error_index = -1; } + /** + * This method returns the current parsing index. + * + * @return The current parsing index + */ public int getIndex () { return index; } + /** + * This method sets the current parsing index to the specified value. + * + * @param index The new parsing index. + */ public void setIndex (int index) { this.index = index; } + /** + * This method returns the error index value. This value defaults to -1 + * unless explicitly set to another value. + * + * @return The error index. + */ public int getErrorIndex () { - return errorIndex; + return error_index; } - public void setErrorIndex (int ei) + /** + * This method sets the error index to the specified value. + * + * @param error_index The new error index + */ + public void setErrorIndex (int error_index) { - errorIndex = ei; + this.error_index = error_index; } + /** + * This method tests the specified object for equality with this + * object. The two objects will be considered equal if and only if + * all of the following conditions are met. + *

      + *

        + *
      • The specified object is not null. + *
      • The specified object is an instance of ParsePosition. + *
      • The specified object has the same index and error index as + * this object. + *
      + * + * @param obj The Object to test for equality against + * this object. + * + * @return true if the specified object is equal to + * this object, false otherwise. + */ public boolean equals (Object obj) { - if (obj != null || ! (obj instanceof ParsePosition)) + if (! (obj instanceof ParsePosition)) return false; + ParsePosition other = (ParsePosition) obj; - return index == other.index && errorIndex == other.errorIndex; + return index == other.index && error_index == other.error_index; + } + + /** + * This method returns a String representation of this + * object. + * + * @return A String that represents this object. + */ + public String toString () + { + return (getClass ().getName () + "[index=" + getIndex () + + ",errorIndex=" + getErrorIndex () + "]"); } } diff --git a/libjava/java/text/SimpleDateFormat.java b/libjava/java/text/SimpleDateFormat.java index 8d914fb3ebf..6366082cfd4 100644 --- a/libjava/java/text/SimpleDateFormat.java +++ b/libjava/java/text/SimpleDateFormat.java @@ -207,6 +207,7 @@ public class SimpleDateFormat extends DateFormat { super(); calendar = new GregorianCalendar(); + computeCenturyStart (); tokens = new Vector(); this.formatData = formatData; compileFormat(pattern); diff --git a/libjava/java/text/StringCharacterIterator.java b/libjava/java/text/StringCharacterIterator.java index 487b09c8220..64af2601df8 100644 --- a/libjava/java/text/StringCharacterIterator.java +++ b/libjava/java/text/StringCharacterIterator.java @@ -1,149 +1,345 @@ -// StringCharacterIterator.java - Iterate over string of Unicode characters. +/* StringCharacterIterator.java -- Iterate over a character range in a string + Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. -/* Copyright (C) 1999, 2000 Free Software Foundation +This file is part of GNU Classpath. - This file is part of libgcj. +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., 59 Temple Place, Suite 330, Boston, MA +02111-1307 USA. + +As a special exception, if you link this library with other files to +produce an executable, this library does not by itself cause the +resulting executable to be covered by the GNU General Public License. +This exception does not however invalidate any other reasons why the +executable file might be covered by the GNU General Public License. */ -This software is copyrighted work licensed under the terms of the -Libgcj License. Please consult the file "LIBGCJ_LICENSE" for -details. */ package java.text; /** + * This class iterates over a range of characters in a String. + * For a given range of text, a beginning and ending index, + * as well as a current index are defined. These values can be queried + * by the methods in this interface. Additionally, various methods allow + * the index to be set. + * + * @author Aaron M. Renn (arenn@urbanophile.com) * @author Tom Tromey - * @date February 22, 1999 - */ -/* Written using "Java Class Libraries", 2nd edition, plus online - * API docs for JDK 1.2 beta from http://www.javasoft.com. - * Status: Believed complete and correct to 1.1. */ - public final class StringCharacterIterator implements CharacterIterator { - public Object clone () + /** + * This is the string to iterate over + */ + private String text; + + /** + * This is the value of the start position of the text range. + */ + private int begin; + + /** + * This is the value of the ending position of the text range. + */ + private int end; + + /** + * This is the current value of the scan index. + */ + private int index; + + /** + * This method initializes a new instance of + * StringCharacterIterator to iterate over the entire + * text of the specified String. The initial index + * value will be set to the first character in the string. + * + * @param text The String to iterate through. + */ + public StringCharacterIterator (String text) { - return (Object) new StringCharacterIterator (text, begin, end, pos); + this (text, 0, text.length (), 0); } - public char current () + /*************************************************************************/ + + /** + * This method initializes a new instance of + * StringCharacterIterator to iterate over the entire + * text of the specified String. The initial index + * value will be set to the specified value. + * + * @param text The String to iterate through. + * @param index The initial index position. + */ + public StringCharacterIterator (String text, int index) { - // This follows JDK 1.2 semantics and not 1.1 semantics. - // In 1.1 we would throw an exception if begin==end. - return (pos < end) ? text.charAt(pos) : CharacterIterator.DONE; + this (text, 0, text.length (), index); } - public boolean equals (Object obj) + /*************************************************************************/ + + /** + * This method initializes a new instance of + * StringCharacterIterator that iterates over the text + * in a subrange of the specified String. The + * beginning and end of the range are specified by the caller, as is + * the initial index position. + * + * @param text The String to iterate through. + * @param begin The beginning position in the character range. + * @param end The ending position in the character range. + * @param index The initial index position. + * + * @param IllegalArgumentException If any of the range values are + * invalid. + */ + public StringCharacterIterator (String text, int begin, int end, int index) { - if (! (obj instanceof StringCharacterIterator)) - return false; - StringCharacterIterator sci = (StringCharacterIterator) obj; - // The spec says "the same text". We take this to mean equals, - // not ==. - return (pos == sci.pos - && begin == sci.begin - && end == sci.end - && text.equals(sci.text)); + int len = text.length (); + + if ((begin < 0) || (begin > len)) + throw new IllegalArgumentException ("Bad begin position"); + + if ((end < begin) || (end > len)) + throw new IllegalArgumentException ("Bad end position"); + + if ((index < begin) || (index > end)) + throw new IllegalArgumentException ("Bad initial index position"); + + this.text = text; + this.begin = begin; + this.end = end; + this.index = index; } - public char first () + /** + * This is a package level constructor that copies the text out of + * an existing StringCharacterIterator and resets the beginning and + * ending index. + * + * @param scci The StringCharacterIterator to copy the info from + * @param begin The beginning index of the range we are interested in. + * @param end The ending index of the range we are interested in. + */ + StringCharacterIterator (StringCharacterIterator sci, int begin, int end) { - pos = begin; - return current (); + this (sci.text, begin, end, begin); } - public int getBeginIndex () + /** + * This method returns the character at the current index position + * + * @return The character at the current index position. + */ + public char current () { - return begin; + return (index < end) ? text.charAt (index) : DONE; } - public int getEndIndex () + /*************************************************************************/ + + /** + * This method increments the current index and then returns the + * character at the new index value. If the index is already at + * getEndIndex () - 1, it will not be incremented. + * + * @return The character at the position of the incremented index + * value, or DONE if the index has reached + * getEndIndex () - 1. + */ + public char next () { - return end; + if (index == end) + return DONE; + + ++index; + return current (); } - public int getIndex () + /*************************************************************************/ + + /** + * This method decrements the current index and then returns the + * character at the new index value. If the index value is already + * at the beginning index, it will not be decremented. + * + * @return The character at the position of the decremented index + * value, or DONE if index was already equal to the + * beginning index value. + */ + public char previous () { - return pos; + if (index == begin) + return DONE; + + --index; + return current (); } - public int hashCode () + /*************************************************************************/ + + /** + * This method sets the index value to the beginning of the range and returns + * the character there. + * + * @return The character at the beginning of the range, or + * DONE if the range is empty. + */ + public char first () { - // FIXME: this is a terrible hash code. Find a better one. - return text.hashCode() + pos + begin + end; + index = begin; + return current (); } + /*************************************************************************/ + + /** + * This method sets the index value to getEndIndex () - 1 and + * returns the character there. If the range is empty, then the index value + * will be set equal to the beginning index. + * + * @return The character at the end of the range, or + * DONE if the range is empty. + */ public char last () { - pos = end; + if (end == begin) + return DONE; + + index = end - 1; return current (); } - public char next () + /*************************************************************************/ + + /** + * This method returns the current value of the index. + * + * @return The current index value + */ + public int getIndex () { - if (pos == end) - return CharacterIterator.DONE; - ++pos; - return current (); + return index; } - public char previous () + /*************************************************************************/ + + /** + * This method sets the value of the index to the specified value, then + * returns the character at that position. + * + * @param index The new index value. + * + * @return The character at the new index value or DONE + * if the index value is equal to getEndIndex. + * + * @exception IllegalArgumentException If the specified index is not valid + */ + public char setIndex (int index) { - if (pos == begin) - return CharacterIterator.DONE; - --pos; + if ((index < begin) || (index > end)) + throw new IllegalArgumentException ("Bad index specified"); + + this.index = index; return current (); } - public char setIndex (int idx) + /*************************************************************************/ + + /** + * This method returns the character position of the first character in the + * range. + * + * @return The index of the first character in the range. + */ + public int getBeginIndex () { - // In 1.1 we would throw an error if `idx == end'. - if (idx < begin || idx > end) - throw new IllegalArgumentException (); - pos = idx; - return current (); + return begin; } - public StringCharacterIterator (String text) + /*************************************************************************/ + + /** + * This method returns the character position of the end of the text range. + * This will actually be the index of the first character following the + * end of the range. In the event the text range is empty, this will be + * equal to the first character in the range. + * + * @return The index of the end of the range. + */ + public int getEndIndex () { - this (text, 0, text.length(), 0); + return end; } - public StringCharacterIterator (String text, int pos) + /*************************************************************************/ + + /** + * This method creates a copy of this CharacterIterator. + * + * @return A copy of this CharacterIterator. + */ + public Object clone () { - this (text, 0, text.length(), pos); + return new StringCharacterIterator (text, begin, end, index); } - public StringCharacterIterator (String text, int begin, int end, int pos) + /*************************************************************************/ + + /** + * This method tests this object for equality againt the specified + * object. This will be true if and only if the specified object: + *

      + *

        + *
      • is not null. + *
      • is an instance of StringCharacterIterator + *
      • has the same text as this object + *
      • has the same beginning, ending, and current index as this object. + *
      + * + * @param obj The object to test for equality against. + * + * @return true if the specified object is equal to this + * object, false otherwise. + */ + public boolean equals (Object obj) { - if (begin < 0 || begin > end || end > text.length() - // In 1.1 we would also throw if `pos == end'. - || pos < begin || pos > end) - throw new IllegalArgumentException (); + if (! (obj instanceof StringCharacterIterator)) + return false; - this.text = text; - this.begin = begin; - this.end = end; - this.pos = pos; + StringCharacterIterator sci = (StringCharacterIterator) obj; + + return (begin == sci.begin + && end == sci.end + && index == sci.index + && text.equals (sci.text)); } - // The online 1.2 docs say that this is "package visible" in the - // method description, but they also say it is public. We choose - // the latter for compatibility with the actual implementation. + /*************************************************************************/ + + /** + * This method allows other classes in java.text to change the value + * of the underlying text being iterated through. + * + * @param text The new String to iterate through. + */ public void setText (String text) { this.text = text; this.begin = 0; this.end = text.length (); - this.pos = 0; + this.index = 0; } - - // String to iterate over. - private String text; - // Current position. - private int pos; - // Start position in string. - private int begin; - // End position in string. - private int end; } -- cgit v1.2.3