/[classpath]/classpath/java/nio/charset/CharsetDecoder.java
ViewVC logotype

Diff of /classpath/java/nio/charset/CharsetDecoder.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by mark, Tue Apr 30 21:37:27 2002 UTC revision 1.4 by mkoch, Fri Nov 8 12:15:32 2002 UTC
# Line 37  exception statement from your version. * Line 37  exception statement from your version. *
37    
38  package java.nio.charset;  package java.nio.charset;
39    
40  import java.nio.*;  import java.nio.ByteBuffer;
41    import java.nio.CharBuffer;
42    
43    /**
44     * @author Jesse Rosenstock
45     * @since 1.4
46     */
47  public abstract class CharsetDecoder  public abstract class CharsetDecoder
48  {  {
49      Charset cs;    private static final int STATE_RESET   = 0;
50      float averageCharsPerByte;    private static final int STATE_CODING  = 1;
51      float maxCharsPerByte;    private static final int STATE_END     = 2;
52      String repl;    private static final int STATE_FLUSHED = 3;
53    
54      protected CharsetDecoder(Charset cs,    private static final String DEFAULT_REPLACEMENT = "\uFFFD";
55                               float averageCharsPerByte,  
56                               float maxCharsPerByte)    private final Charset charset;
57      {    private final float averageCharsPerByte;
58          this.cs = cs;    private final float maxCharsPerByte;
59          this.averageCharsPerByte = averageCharsPerByte;    private String replacement;
60          this.maxCharsPerByte     = maxCharsPerByte;  
61      }    private int state = STATE_RESET;
62        
63      public float averageCharsPerByte()    private CodingErrorAction malformedInputAction
64      {      = CodingErrorAction.REPORT;
65          return averageCharsPerByte;    private CodingErrorAction unmappableCharacterAction
66      }      = CodingErrorAction.REPORT;
67    
68      public Charset charset()    private CharsetDecoder (Charset cs, float averageCharsPerByte,
69      {                            float maxCharsPerByte, String replacement)
70          return cs;    {
71      }      if (averageCharsPerByte <= 0.0f)
72          throw new IllegalArgumentException ("Non-positive averageCharsPerByte");
73      public CharBuffer decode(ByteBuffer in)      if (maxCharsPerByte <= 0.0f)
74      {        throw new IllegalArgumentException ("Non-positive maxCharsPerByte");
75          CharBuffer x = CharBuffer.allocate(in.remaining());  
76          decode(in, x, false);        this.charset = cs;
77          x.rewind();      this.averageCharsPerByte
78          return x;        = averageCharsPerByte;
79      }      this.maxCharsPerByte
80              = maxCharsPerByte;
81      public CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput)      this.replacement = replacement;
82      {      implReplaceWith (replacement);
83          return decodeLoop(in,out);    }
84      }  
85      protected CharsetDecoder (Charset cs, float averageCharsPerByte,
86      protected abstract  CoderResult decodeLoop(ByteBuffer in, CharBuffer out);                              float maxCharsPerByte)
87      {
88      public Charset detectedCharset()      this (cs, averageCharsPerByte, maxCharsPerByte, DEFAULT_REPLACEMENT);
89      {    }
90          return charset();  
91      }    public final float averageCharsPerByte ()
92          {
93      public CoderResult flush(CharBuffer out)      return averageCharsPerByte;
94      {    }
95          return implFlush(out);  
96      }    public final Charset charset ()
97      protected  CoderResult implFlush(CharBuffer out)    {
98      {      return charset;
99          return null;    }
100      }  
101      protected  void implOnMalformedInput(CodingErrorAction newAction)    public final CharBuffer decode (ByteBuffer in)
102      {      throws CharacterCodingException
103      }    {
104      protected  void implOnUnmappableCharacter(CodingErrorAction newAction)      // XXX: Sun's Javadoc seems to contradict itself saying an
105      {      // IllegalStateException is thrown "if a decoding operation is already
106      }      // in progress" and also that "it resets this Decoder".
107      protected  void implReplaceWith(String newReplacement)      // Should we check to see that the state is reset, or should we
108      {      // call reset()?
109      }      if (state != STATE_RESET)
110      protected  void implReset()        throw new IllegalStateException ();
111      {  
112      }      // REVIEW: Using max instead of average may allocate a very large
113        // buffer.  Maybe we should do something more efficient?
114      public boolean isAutoDetecting()      int remaining = in.remaining ();
115      {      int n = (int) (remaining * maxCharsPerByte ());
116          return true;      CharBuffer out = CharBuffer.allocate (n);
117      }  
118            if (remaining == 0)
119      public boolean isCharsetDetected()        {
120      {          state = STATE_FLUSHED;
121          return true;          return out;
122      }        }
123      public CodingErrorAction malformedInputAction()  
124      {      CoderResult cr = decode (in, out, true);
125          return null;      if (cr.isError ())
126      }        cr.throwException ();
127      public float maxCharsPerByte()  
128      {      cr = flush (out);
129          return maxCharsPerByte;      if (cr.isError ())
130      }        cr.throwException ();
131      public CharsetDecoder onMalformedInput(CodingErrorAction newAction)  
132      {      out.flip ();
133          return null;      return out;
134      }    }
135      public CharsetDecoder onUnmappableCharacter(CodingErrorAction newAction)  
136      {    public final CoderResult decode (ByteBuffer in, CharBuffer out,
137          return null;                                     boolean endOfInput)
138      }    {
139      public String replacement()      int newState = endOfInput ? STATE_END : STATE_CODING;
140      {      // XXX: Need to check for "previous step was an invocation [not] of
141          return repl;      // this method with a value of true for the endOfInput parameter but
142      }      // a return value indicating an incomplete decoding operation"
143        // XXX: We will not check the previous return value, just
144      public CharsetDecoder replaceWith(String newReplacement)      // that the previous call passed true for endOfInput
145      {      if (state != STATE_RESET && state != STATE_CODING
146          return null;          && !(endOfInput && state == STATE_END))
147      }        throw new IllegalStateException ();
148        state = newState;
149      public CharsetDecoder reset()  
150      {      for (;;)
151          return null;        {
152      }          CoderResult cr;
153            try
154              {
155                cr = decodeLoop (in, out);
156              }
157            catch (RuntimeException e)
158              {
159                throw new CoderMalfunctionError (e);
160              }
161    
162            if (cr.isOverflow ())
163              return cr;
164    
165            if (cr.isUnderflow ())
166              {
167                if (endOfInput && in.hasRemaining ())
168                  cr = CoderResult.malformedForLength (in.remaining ());
169                else
170                  return cr;
171              }
172    
173            CodingErrorAction action = cr.isMalformed ()
174                                         ? malformedInputAction
175                                         : unmappableCharacterAction;
176    
177            if (action == CodingErrorAction.REPORT)
178              return cr;
179    
180            if (action == CodingErrorAction.REPLACE)
181              {
182                if (out.remaining () < replacement.length ())
183                  return CoderResult.OVERFLOW;
184                out.put (replacement);
185              }
186    
187            in.position (in.position () + cr.length ());
188          }
189      }
190    
191      protected abstract CoderResult decodeLoop (ByteBuffer in, CharBuffer out);
192    
193      public Charset detectedCharset ()
194      {
195        throw new UnsupportedOperationException ();
196      }
197            
198      public CodingErrorAction unmappableCharacterAction()    public final CoderResult flush (CharBuffer out)
199      {    {
200          return null;      // It seems weird that you can flush after reset, but Sun's javadoc
201      }      // says an IllegalStateException is thrown "If the previous step of the
202        // current decoding operation was an invocation neither of the reset
203        // method nor ... of the three-argument decode method with a value of
204        // true for the endOfInput parameter."
205        // Further note that flush() only requires that there not be
206        // an IllegalStateException if the previous step was a call to
207        // decode with true as the last argument.  It does not require
208        // that the call succeeded.  decode() does require that it succeeded.
209        // XXX: test this to see if reality matches javadoc
210        if (state != STATE_RESET && state != STATE_END)
211          throw new IllegalStateException ();
212    
213        state = STATE_FLUSHED;
214        return implFlush (out);
215      }
216    
217      protected CoderResult implFlush (CharBuffer out)
218      {
219        return CoderResult.UNDERFLOW;
220      }
221    
222      public final CharsetDecoder onMalformedInput (CodingErrorAction newAction)
223      {
224        if (newAction == null)
225          throw new IllegalArgumentException ("Null action");
226    
227        malformedInputAction = newAction;
228        implOnMalformedInput (newAction);
229        return this;
230      }
231    
232      protected void implOnMalformedInput (CodingErrorAction newAction)
233      {
234        // default implementation does nothing
235      }
236    
237      protected void implOnUnmappableCharacter (CodingErrorAction newAction)
238      {
239        // default implementation does nothing
240      }
241    
242      protected void implReplaceWith (String newReplacement)
243      {
244        // default implementation does nothing
245      }
246    
247      protected void implReset ()
248      {
249        // default implementation does nothing
250      }
251    
252      public boolean isAutoDetecting ()
253      {
254        return false;
255      }
256    
257      public boolean isCharsetDetected ()
258      {
259        throw new UnsupportedOperationException ();
260      }
261    
262      public CodingErrorAction malformedInputAction ()
263      {
264        return malformedInputAction;
265      }
266    
267      public final float maxCharsPerByte ()
268      {
269        return maxCharsPerByte;
270      }
271    
272      public final CharsetDecoder onUnmappableCharacter
273        (CodingErrorAction newAction)
274      {
275        if (newAction == null)
276          throw new IllegalArgumentException ("Null action");
277    
278        unmappableCharacterAction = newAction;
279        implOnUnmappableCharacter (newAction);
280        return this;
281      }
282    
283      public final String replacement ()
284      {
285        return replacement;
286      }
287    
288      public final CharsetDecoder replaceWith (String newReplacement)
289      {
290        if (newReplacement == null)
291          throw new IllegalArgumentException ("Null replacement");
292        if (newReplacement.length () == 0)
293          throw new IllegalArgumentException ("Empty replacement");
294        // XXX: what about maxCharsPerByte?
295    
296        this.replacement = newReplacement;
297        implReplaceWith (newReplacement);
298        return this;
299      }
300    
301      public final CharsetDecoder reset ()
302      {
303        state = STATE_RESET;
304        implReset ();
305        return this;
306      }
307    
308      public CodingErrorAction unmappableCharacterAction ()
309      {
310        return unmappableCharacterAction;
311      }
312  }  }

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26