summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/nio/charset/CharsetDecoder.java
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/java/nio/charset/CharsetDecoder.java
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/classpath/java/nio/charset/CharsetDecoder.java')
-rw-r--r--libjava/classpath/java/nio/charset/CharsetDecoder.java317
1 files changed, 317 insertions, 0 deletions
diff --git a/libjava/classpath/java/nio/charset/CharsetDecoder.java b/libjava/classpath/java/nio/charset/CharsetDecoder.java
new file mode 100644
index 000000000..cf43feafd
--- /dev/null
+++ b/libjava/classpath/java/nio/charset/CharsetDecoder.java
@@ -0,0 +1,317 @@
+/* CharsetDecoder.java --
+ Copyright (C) 2002 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., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package java.nio.charset;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+
+/**
+ * @author Jesse Rosenstock
+ * @since 1.4
+ */
+public abstract class CharsetDecoder
+{
+ private static final int STATE_RESET = 0;
+ private static final int STATE_CODING = 1;
+ private static final int STATE_END = 2;
+ private static final int STATE_FLUSHED = 3;
+
+ private static final String DEFAULT_REPLACEMENT = "\uFFFD";
+
+ private final Charset charset;
+ private final float averageCharsPerByte;
+ private final float maxCharsPerByte;
+ private String replacement;
+
+ private int state = STATE_RESET;
+
+ private CodingErrorAction malformedInputAction
+ = CodingErrorAction.REPORT;
+ private CodingErrorAction unmappableCharacterAction
+ = CodingErrorAction.REPORT;
+
+ private CharsetDecoder (Charset cs, float averageCharsPerByte,
+ float maxCharsPerByte, String replacement)
+ {
+ if (averageCharsPerByte <= 0.0f)
+ throw new IllegalArgumentException ("Non-positive averageCharsPerByte");
+ if (maxCharsPerByte <= 0.0f)
+ throw new IllegalArgumentException ("Non-positive maxCharsPerByte");
+
+ this.charset = cs;
+ this.averageCharsPerByte
+ = averageCharsPerByte;
+ this.maxCharsPerByte
+ = maxCharsPerByte;
+ this.replacement = replacement;
+ implReplaceWith (replacement);
+ }
+
+ protected CharsetDecoder (Charset cs, float averageCharsPerByte,
+ float maxCharsPerByte)
+ {
+ this (cs, averageCharsPerByte, maxCharsPerByte, DEFAULT_REPLACEMENT);
+ }
+
+ public final float averageCharsPerByte ()
+ {
+ return averageCharsPerByte;
+ }
+
+ public final Charset charset ()
+ {
+ return charset;
+ }
+
+ public final CharBuffer decode (ByteBuffer in)
+ throws CharacterCodingException
+ {
+ // XXX: Sun's Javadoc seems to contradict itself saying an
+ // IllegalStateException is thrown "if a decoding operation is already
+ // in progress" and also that "it resets this Decoder".
+ // Should we check to see that the state is reset, or should we
+ // call reset()?
+ if (state != STATE_RESET)
+ throw new IllegalStateException ();
+
+ // REVIEW: Using max instead of average may allocate a very large
+ // buffer. Maybe we should do something more efficient?
+ int remaining = in.remaining ();
+ int n = (int) (remaining * maxCharsPerByte ());
+ CharBuffer out = CharBuffer.allocate (n);
+
+ if (remaining == 0)
+ {
+ state = STATE_FLUSHED;
+ return out;
+ }
+
+ CoderResult cr = decode (in, out, true);
+ if (cr.isError ())
+ cr.throwException ();
+
+ cr = flush (out);
+ if (cr.isError ())
+ cr.throwException ();
+
+ reset();
+ out.flip ();
+
+ // Unfortunately, resizing the actual charbuffer array is required.
+ char[] resized = new char[out.remaining()];
+ out.get(resized);
+ return CharBuffer.wrap(resized);
+ }
+
+ public final CoderResult decode (ByteBuffer in, CharBuffer out,
+ boolean endOfInput)
+ {
+ int newState = endOfInput ? STATE_END : STATE_CODING;
+ // XXX: Need to check for "previous step was an invocation [not] of
+ // this method with a value of true for the endOfInput parameter but
+ // a return value indicating an incomplete decoding operation"
+ // XXX: We will not check the previous return value, just
+ // that the previous call passed true for endOfInput
+ if (state != STATE_RESET && state != STATE_CODING
+ && !(endOfInput && state == STATE_END))
+ throw new IllegalStateException ();
+ state = newState;
+
+ for (;;)
+ {
+ CoderResult cr;
+ try
+ {
+ cr = decodeLoop (in, out);
+ }
+ catch (RuntimeException e)
+ {
+ throw new CoderMalfunctionError (e);
+ }
+
+ if (cr.isOverflow ())
+ return cr;
+
+ if (cr.isUnderflow ())
+ {
+ if (endOfInput && in.hasRemaining ())
+ cr = CoderResult.malformedForLength (in.remaining ());
+ else
+ return cr;
+ }
+
+ CodingErrorAction action = cr.isMalformed ()
+ ? malformedInputAction
+ : unmappableCharacterAction;
+
+ if (action == CodingErrorAction.REPORT)
+ return cr;
+
+ if (action == CodingErrorAction.REPLACE)
+ {
+ if (out.remaining () < replacement.length ())
+ return CoderResult.OVERFLOW;
+ out.put (replacement);
+ }
+
+ in.position (in.position () + cr.length ());
+ }
+ }
+
+ protected abstract CoderResult decodeLoop (ByteBuffer in, CharBuffer out);
+
+ public Charset detectedCharset ()
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public final CoderResult flush (CharBuffer out)
+ {
+ // It seems weird that you can flush after reset, but Sun's javadoc
+ // says an IllegalStateException is thrown "If the previous step of the
+ // current decoding operation was an invocation neither of the reset
+ // method nor ... of the three-argument decode method with a value of
+ // true for the endOfInput parameter."
+ // Further note that flush() only requires that there not be
+ // an IllegalStateException if the previous step was a call to
+ // decode with true as the last argument. It does not require
+ // that the call succeeded. decode() does require that it succeeded.
+ // XXX: test this to see if reality matches javadoc
+ if (state != STATE_RESET && state != STATE_END)
+ throw new IllegalStateException ();
+
+ state = STATE_FLUSHED;
+ return implFlush (out);
+ }
+
+ protected CoderResult implFlush (CharBuffer out)
+ {
+ return CoderResult.UNDERFLOW;
+ }
+
+ public final CharsetDecoder onMalformedInput (CodingErrorAction newAction)
+ {
+ if (newAction == null)
+ throw new IllegalArgumentException ("Null action");
+
+ malformedInputAction = newAction;
+ implOnMalformedInput (newAction);
+ return this;
+ }
+
+ protected void implOnMalformedInput (CodingErrorAction newAction)
+ {
+ // default implementation does nothing
+ }
+
+ protected void implOnUnmappableCharacter (CodingErrorAction newAction)
+ {
+ // default implementation does nothing
+ }
+
+ protected void implReplaceWith (String newReplacement)
+ {
+ // default implementation does nothing
+ }
+
+ protected void implReset ()
+ {
+ // default implementation does nothing
+ }
+
+ public boolean isAutoDetecting ()
+ {
+ return false;
+ }
+
+ public boolean isCharsetDetected ()
+ {
+ throw new UnsupportedOperationException ();
+ }
+
+ public CodingErrorAction malformedInputAction ()
+ {
+ return malformedInputAction;
+ }
+
+ public final float maxCharsPerByte ()
+ {
+ return maxCharsPerByte;
+ }
+
+ public final CharsetDecoder onUnmappableCharacter
+ (CodingErrorAction newAction)
+ {
+ if (newAction == null)
+ throw new IllegalArgumentException ("Null action");
+
+ unmappableCharacterAction = newAction;
+ implOnUnmappableCharacter (newAction);
+ return this;
+ }
+
+ public final String replacement ()
+ {
+ return replacement;
+ }
+
+ public final CharsetDecoder replaceWith (String newReplacement)
+ {
+ if (newReplacement == null)
+ throw new IllegalArgumentException ("Null replacement");
+ if (newReplacement.length () == 0)
+ throw new IllegalArgumentException ("Empty replacement");
+ // XXX: what about maxCharsPerByte?
+
+ this.replacement = newReplacement;
+ implReplaceWith (newReplacement);
+ return this;
+ }
+
+ public final CharsetDecoder reset ()
+ {
+ state = STATE_RESET;
+ implReset ();
+ return this;
+ }
+
+ public CodingErrorAction unmappableCharacterAction ()
+ {
+ return unmappableCharacterAction;
+ }
+}