001/* CoderResult.java -- 
002   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package java.nio.charset;
039
040import java.lang.ref.WeakReference;
041import java.nio.BufferOverflowException;
042import java.nio.BufferUnderflowException;
043import java.util.HashMap;
044
045/**
046 * @author Jesse Rosenstock
047 * @since 1.4
048 */
049public class CoderResult
050{ 
051  private static final int TYPE_MALFORMED  = 0;
052  private static final int TYPE_OVERFLOW   = 1;
053  private static final int TYPE_UNDERFLOW  = 2;
054  private static final int TYPE_UNMAPPABLE = 3;
055
056  public static final CoderResult OVERFLOW
057    = new CoderResult (TYPE_OVERFLOW, 0);
058  public static final CoderResult UNDERFLOW
059    = new CoderResult (TYPE_UNDERFLOW, 0);
060  
061  private static final String[] names
062    = { "MALFORMED", "OVERFLOW", "UNDERFLOW", "UNMAPPABLE" };
063
064  private static final Cache malformedCache
065    = new Cache ()
066      {
067        protected CoderResult make (int length)
068        {
069          return new CoderResult (TYPE_MALFORMED, length);
070        }
071      };
072
073  private static final Cache unmappableCache
074    = new Cache ()
075      {
076        protected CoderResult make (int length)
077        {
078          return new CoderResult (TYPE_UNMAPPABLE, length);
079        }
080      };
081
082  private final int type;
083  private final int length;
084
085  // Package-private to avoid a trampoline constructor.
086  CoderResult (int type, int length)
087  {
088    this.type = type;
089    this.length = length;
090  }
091
092  public boolean isError ()
093  {
094    return length > 0;
095  }
096
097  public boolean isMalformed ()
098  {
099    return type == TYPE_MALFORMED;
100  }
101
102  public boolean isOverflow ()
103  {
104    return type == TYPE_OVERFLOW;
105  }
106
107  public boolean isUnderflow ()
108  {
109    return type == TYPE_UNDERFLOW;
110  }
111
112  public boolean isUnmappable ()
113  {
114    return type == TYPE_UNMAPPABLE;
115  }
116
117  public int length ()
118  {
119    if (length <= 0)
120      throw new UnsupportedOperationException ();
121    else
122      return length;
123  }
124
125  public static CoderResult malformedForLength (int length)
126  {
127    return malformedCache.get (length);
128  }
129    
130  public void throwException ()
131    throws CharacterCodingException
132  {
133    switch (type)
134      {
135        case TYPE_MALFORMED:
136          throw new MalformedInputException (length);
137        case TYPE_OVERFLOW:
138          throw new BufferOverflowException ();
139        case TYPE_UNDERFLOW:
140          throw new BufferUnderflowException ();
141        case TYPE_UNMAPPABLE:
142          throw new UnmappableCharacterException (length);
143      }
144  }
145
146  public String toString ()
147  {
148    String name = names[type];
149    return (length > 0) ? name + '[' + length + ']' : name;
150  }
151
152  public static CoderResult unmappableForLength (int length)
153  {
154    return unmappableCache.get (length);
155  }    
156
157  private abstract static class Cache
158  {
159    private final HashMap cache;
160
161    // Package-private to avoid a trampoline constructor.
162    Cache ()
163    {
164      cache = new HashMap ();
165    }
166
167    // Package-private to avoid a trampoline.
168    synchronized CoderResult get (int length)
169    {
170      if (length <= 0)
171        throw new IllegalArgumentException ("Non-positive length");
172
173      Integer len = Integer.valueOf (length);
174      CoderResult cr = null;
175      Object o;
176      if ((o = cache.get (len)) != null)
177        cr = (CoderResult) ((WeakReference) o).get ();
178      if (cr == null)
179        {
180          cr = make (length);
181          cache.put (len, new WeakReference (cr));
182        }
183
184      return cr;
185    }
186
187    protected abstract CoderResult make (int length);
188  }
189}