Merge from the pain train
[official-gcc.git] / libjava / java / nio / charset / Charset.java
blobc7672c1c3df74ab7d0e9d3d9dec1e2476fe56524
1 /* Charset.java --
2 Copyright (C) 2002, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.nio.charset;
41 import gnu.java.nio.charset.Provider;
43 import java.nio.ByteBuffer;
44 import java.nio.CharBuffer;
45 import java.nio.charset.spi.CharsetProvider;
46 import java.util.Collections;
47 import java.util.HashSet;
48 import java.util.Iterator;
49 import java.util.Locale;
50 import java.util.Set;
51 import java.util.SortedMap;
52 import java.util.TreeMap;
54 /**
55 * @author Jesse Rosenstock
56 * @since 1.4
58 public abstract class Charset implements Comparable
60 private static CharsetEncoder cachedEncoder;
61 private static CharsetDecoder cachedDecoder;
63 static
65 synchronized (Charset.class)
67 cachedEncoder = null;
68 cachedDecoder = null;
72 private final String canonicalName;
73 private final String[] aliases;
75 protected Charset (String canonicalName, String[] aliases)
77 checkName (canonicalName);
78 if (aliases != null)
80 int n = aliases.length;
81 for (int i = 0; i < n; ++i)
82 checkName (aliases[i]);
85 this.canonicalName = canonicalName;
86 this.aliases = aliases;
89 /**
90 * @throws IllegalCharsetNameException if the name is illegal
92 private static void checkName (String name)
94 int n = name.length ();
96 if (n == 0)
97 throw new IllegalCharsetNameException (name);
99 char ch = name.charAt (0);
100 if (!(('A' <= ch && ch <= 'Z')
101 || ('a' <= ch && ch <= 'z')
102 || ('0' <= ch && ch <= '9')))
103 throw new IllegalCharsetNameException (name);
105 for (int i = 1; i < n; ++i)
107 ch = name.charAt (i);
108 if (!(('A' <= ch && ch <= 'Z')
109 || ('a' <= ch && ch <= 'z')
110 || ('0' <= ch && ch <= '9')
111 || ch == '-' || ch == '.' || ch == ':' || ch == '_'))
112 throw new IllegalCharsetNameException (name);
116 public static boolean isSupported (String charsetName)
118 return charsetForName (charsetName) != null;
122 * Returns the Charset instance for the charset of the given name.
124 * @param charsetName
125 * @return
126 * @throws UnsupportedCharsetException if this VM does not support
127 * the charset of the given name.
128 * @throws IllegalCharsetNameException if the given charset name is
129 * legal.
130 * @throws IllegalArgumentException if <code>charsetName</code> is null.
132 public static Charset forName (String charsetName)
134 // Throws IllegalArgumentException as the JDK does.
135 if(charsetName == null)
136 throw new IllegalArgumentException("Charset name must not be null.");
138 Charset cs = charsetForName (charsetName);
139 if (cs == null)
140 throw new UnsupportedCharsetException (charsetName);
141 cachedDecoder = null;
142 cachedEncoder = null;
143 return cs;
147 * Retrieves a charset for the given charset name.
149 * @return A charset object for the charset with the specified name, or
150 * <code>null</code> if no such charset exists.
152 * @throws IllegalCharsetNameException if the name is illegal
154 private static Charset charsetForName(String charsetName)
156 checkName (charsetName);
157 return provider ().charsetForName (charsetName);
160 public static SortedMap availableCharsets()
162 TreeMap charsets = new TreeMap(String.CASE_INSENSITIVE_ORDER);
164 for (Iterator i = provider ().charsets (); i.hasNext (); )
166 Charset cs = (Charset) i.next ();
167 charsets.put (cs.name (), cs);
170 return Collections.unmodifiableSortedMap(charsets);
173 // XXX: we need to support multiple providers, reading them from
174 // java.nio.charset.spi.CharsetProvider in the resource directory
175 // META-INF/services
176 private static CharsetProvider provider()
178 return Provider.provider();
181 public final String name ()
183 return canonicalName;
186 public final Set aliases ()
188 if (aliases == null)
189 return Collections.EMPTY_SET;
191 // should we cache the aliasSet instead?
192 int n = aliases.length;
193 HashSet aliasSet = new HashSet (n);
194 for (int i = 0; i < n; ++i)
195 aliasSet.add (aliases[i]);
196 return Collections.unmodifiableSet (aliasSet);
199 public String displayName ()
201 return canonicalName;
204 public String displayName (Locale locale)
206 return canonicalName;
209 public final boolean isRegistered ()
211 return (!canonicalName.startsWith ("x-")
212 && !canonicalName.startsWith ("X-"));
215 public abstract boolean contains (Charset cs);
217 public abstract CharsetDecoder newDecoder ();
219 public abstract CharsetEncoder newEncoder ();
221 public boolean canEncode ()
223 return true;
226 public final ByteBuffer encode (CharBuffer cb)
230 // NB: This implementation serializes different threads calling
231 // Charset.encode(), a potential performance problem. It might
232 // be better to remove the cache, or use ThreadLocal to cache on
233 // a per-thread basis.
234 synchronized (Charset.class)
236 if (cachedEncoder == null)
238 cachedEncoder = newEncoder ()
239 .onMalformedInput (CodingErrorAction.REPLACE)
240 .onUnmappableCharacter (CodingErrorAction.REPLACE);
243 return cachedEncoder.encode (cb);
246 catch (CharacterCodingException e)
248 throw new AssertionError (e);
252 public final ByteBuffer encode (String str)
254 return encode (CharBuffer.wrap (str));
257 public final CharBuffer decode (ByteBuffer bb)
261 // NB: This implementation serializes different threads calling
262 // Charset.decode(), a potential performance problem. It might
263 // be better to remove the cache, or use ThreadLocal to cache on
264 // a per-thread basis.
265 synchronized (Charset.class)
267 if (cachedDecoder == null)
269 cachedDecoder = newDecoder ()
270 .onMalformedInput (CodingErrorAction.REPLACE)
271 .onUnmappableCharacter (CodingErrorAction.REPLACE);
274 return cachedDecoder.decode (bb);
277 catch (CharacterCodingException e)
279 throw new AssertionError (e);
283 public final int compareTo (Object ob)
285 return canonicalName.compareToIgnoreCase (((Charset) ob).canonicalName);
288 public final int hashCode ()
290 return canonicalName.hashCode ();
293 public final boolean equals (Object ob)
295 if (ob instanceof Charset)
296 return canonicalName.equalsIgnoreCase (((Charset) ob).canonicalName);
297 else
298 return false;
301 public final String toString ()
303 return canonicalName;