2002-06-06 James Clark <jjc@jclark.com>
[official-gcc.git] / libjava / gnu / gcj / convert / UnicodeToBytes.java
blob0785d7ea43ed92499ece7e2d53ef6fc0e1926465
1 /* Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation
3 This file is part of libgcj.
5 This software is copyrighted work licensed under the terms of the
6 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
7 details. */
9 package gnu.gcj.convert;
11 public abstract class UnicodeToBytes extends IOConverter
13 /** Buffer to emit bytes to.
14 * The locations buf[count] ... buf[buf.length-1] are available. */
15 public byte[] buf;
16 public int count;
18 // The name of the default encoding.
19 static String defaultEncoding;
21 /* These keep a small cache of encoders for reuse. The array holds
22 the actual encoders. The currCachePos is the next value we are
23 going to replace in the cache. We don't just throw the data away
24 if the cache is full, because if the cache filled up with stuff we
25 don't need then the cache would be worthless. We instead
26 circulate through the cache the implement kind of an LRU
27 algorithm. */
28 private static final int CACHE_SIZE = 4; // A power of 2 for speed
29 private static UnicodeToBytes[] encoderCache
30 = new UnicodeToBytes[CACHE_SIZE];
31 private static int currCachePos = 0;
33 public abstract String getName();
35 public static UnicodeToBytes getDefaultEncoder()
37 try
39 synchronized (UnicodeToBytes.class)
41 if (defaultEncoding == null)
43 String encoding
44 = canonicalize (System.getProperty("file.encoding",
45 "8859_1"));
46 String className = "gnu.gcj.convert.Output_" + encoding;
47 try
49 Class defaultEncodingClass = Class.forName(className);
50 defaultEncoding = encoding;
52 catch (ClassNotFoundException ex)
54 throw new NoClassDefFoundError("missing default encoding "
55 + encoding + " (class "
56 + className
57 + " not found)");
62 return getEncoder (defaultEncoding);
64 catch (Throwable ex)
66 return new Output_8859_1();
70 /** Get a char-stream->byte-stream converter given an encoding name. */
71 public static UnicodeToBytes getEncoder (String encoding)
72 throws java.io.UnsupportedEncodingException
74 /* First hunt in our cache to see if we have a encoder that is
75 already allocated. */
76 synchronized (UnicodeToBytes.class)
78 int i;
79 for (i = 0; i < encoderCache.length; ++i)
81 if (encoderCache[i] != null
82 && encoding.equals(encoderCache[i].getName ()))
84 UnicodeToBytes rv = encoderCache[i];
85 encoderCache[i] = null;
86 return rv;
91 String className = "gnu.gcj.convert.Output_" + canonicalize (encoding);
92 Class encodingClass;
93 try
95 encodingClass = Class.forName(className);
96 return (UnicodeToBytes) encodingClass.newInstance();
98 catch (Throwable ex)
102 // We pass the original name to iconv and let it handle
103 // its own aliasing.
104 return new Output_iconv (encoding);
106 catch (Throwable _)
108 // Put the original exception in the throwable.
109 throw new java.io.UnsupportedEncodingException(encoding + " ("
110 + ex + ')');
115 public final void setOutput(byte[] buffer, int count)
117 this.buf = buffer;
118 this.count = count;
121 /** Convert chars to bytes.
122 * Converted bytes are written to buf, starting at count.
123 * @param inbuffer source of characters to convert
124 * @param inpos index of initial character in inbuffer to convert
125 * @param inlength number of characters to convert
126 * @return number of chars converted
127 * Also, this.count is increment by the number of bytes converted.
129 public abstract int write (char[] inbuffer, int inpos, int inlength);
131 /** Convert chars to bytes.
132 * Converted bytes are written to buf, starting at count.
133 * @param str source of characters to convert
134 * @param inpos index of initial character in str to convert
135 * @param inlength number of characters to convert
136 * @param work if non-null, a buffer than can be used
137 * @return number of chars converted
138 * Also, this.count is increment by the number of bytes converted.
140 public int write (String str, int inpos, int inlength, char[] work)
142 if (work == null)
143 work = new char[inlength];
144 int srcEnd = inpos + (inlength > work.length ? work.length : inlength);
145 str.getChars(inpos, srcEnd, work, 0);
146 return write(work, 0, srcEnd - inpos);
150 * Returns true when the converter has consumed some bytes that are
151 * not yet converted to characters because further continuation
152 * bytes are needed. Defaults to false, should be overridden by
153 * decoders that internally store some bytes.
155 public boolean havePendingBytes()
157 return false;
160 /** Indicate that the converter is resuable.
161 * This class keeps track of converters on a per-encoding basis.
162 * When done with an encoder you may call this method to indicate
163 * that it can be reused later.
165 public void done ()
167 synchronized (UnicodeToBytes.class)
169 this.buf = null;
170 this.count = 0;
172 encoderCache[currCachePos] = this;
173 currCachePos = (currCachePos + 1) % CACHE_SIZE;