[armedbear-cvs] r12321 - trunk/abcl/src/org/armedbear/lisp/util
Erik Huelsmann
ehuelsmann at common-lisp.net
Fri Jan 1 18:26:31 UTC 2010
Author: ehuelsmann
Date: Fri Jan 1 13:26:24 2010
New Revision: 12321
Log:
Fix ticket #75: infinite loop while writing unmappable
characters to an output stream - while at it,
fix the input side too.
Added:
trunk/abcl/src/org/armedbear/lisp/util/RACFMalformedInputException.java (contents, props changed)
trunk/abcl/src/org/armedbear/lisp/util/RACFUnmappableCharacterException.java (contents, props changed)
Modified:
trunk/abcl/src/org/armedbear/lisp/util/RandomAccessCharacterFile.java
Added: trunk/abcl/src/org/armedbear/lisp/util/RACFMalformedInputException.java
==============================================================================
--- (empty file)
+++ trunk/abcl/src/org/armedbear/lisp/util/RACFMalformedInputException.java Fri Jan 1 13:26:24 2010
@@ -0,0 +1,68 @@
+/*
+ * RACFMalformedInputException.java
+ *
+ * Copyright (C) 2009 Erik Huelsmann
+ * $Id$
+ *
+ * This program 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
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * 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 org.armedbear.lisp.util;
+
+import java.nio.charset.MalformedInputException;
+
+
+/** Class - derived from MalformedInputException -
+ * which holds information required to allow higher level
+ * systems to invoke a lisp restart function to set replacement characters.
+ */
+public class RACFMalformedInputException
+ extends MalformedInputException {
+
+ final int position;
+ final char character;
+ final String charsetName;
+
+ public RACFMalformedInputException(int position, char character,
+ String charsetName) {
+ super(1); // 1 == fake length
+ this.position = position;
+ this.character = character;
+ this.charsetName = charsetName;
+ }
+
+ @Override
+ public String getMessage() {
+ return "Input value 0x" + Integer.toHexString(character)
+ + " is malformed while recoding with charset " + charsetName;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+}
\ No newline at end of file
Added: trunk/abcl/src/org/armedbear/lisp/util/RACFUnmappableCharacterException.java
==============================================================================
--- (empty file)
+++ trunk/abcl/src/org/armedbear/lisp/util/RACFUnmappableCharacterException.java Fri Jan 1 13:26:24 2010
@@ -0,0 +1,68 @@
+/*
+ * RACFUnmappableCharacterException.java
+ *
+ * Copyright (C) 2009 Erik Huelsmann
+ * $Id$
+ *
+ * This program 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
+ * of the License, or (at your option) any later version.
+ *
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * 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 org.armedbear.lisp.util;
+
+import java.nio.charset.UnmappableCharacterException;
+
+
+/** Class - derived from UnmappableCharacterException -
+ * which holds information required to allow higher level
+ * systems to invoke a lisp restart function to set replacement characters.
+ */
+public class RACFUnmappableCharacterException
+ extends UnmappableCharacterException {
+
+ final int position;
+ final char character;
+ final String charsetName;
+
+ public RACFUnmappableCharacterException(int position, char character,
+ String charsetName) {
+ super(1); // 1 == fake length
+ this.position = position;
+ this.character = character;
+ this.charsetName = charsetName;
+ }
+
+ @Override
+ public String getMessage() {
+ return "Character \\U" + Integer.toHexString(character)
+ + " can't be recoded using charset " + charsetName;
+ }
+
+ public int getPosition() {
+ return position;
+ }
+
+}
\ No newline at end of file
Modified: trunk/abcl/src/org/armedbear/lisp/util/RandomAccessCharacterFile.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/util/RandomAccessCharacterFile.java (original)
+++ trunk/abcl/src/org/armedbear/lisp/util/RandomAccessCharacterFile.java Fri Jan 1 13:26:24 2010
@@ -280,12 +280,7 @@
fcn = raf.getChannel();
- cset = (encoding == null) ? Charset.defaultCharset() : Charset.forName(encoding);
- cdec = cset.newDecoder();
- cdec.onMalformedInput(CodingErrorAction.REPLACE);
- cdec.onUnmappableCharacter(CodingErrorAction.REPLACE);
- cenc = cset.newEncoder();
-
+ setEncoding(encoding);
bbuf = ByteBuffer.allocate(BUFSIZ);
// there is no readable data available in the buffers.
@@ -304,6 +299,15 @@
outputStream = new RandomAccessOutputStream();
}
+ public void setEncoding(String encoding) {
+ cset = (encoding == null)
+ ? Charset.defaultCharset() : Charset.forName(encoding);
+ cdec = cset.newDecoder();
+ cdec.onMalformedInput(CodingErrorAction.REPLACE);
+ cdec.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ cenc = cset.newEncoder();
+ }
+
public Writer getWriter() {
return writer;
}
@@ -365,6 +369,18 @@
atEof = ! ensureReadBbuf(decodeWasUnderflow);
CoderResult r = cdec.decode(bbuf, cbuf, atEof );
decodeWasUnderflow = (CoderResult.UNDERFLOW == r);
+ if (r.isMalformed())
+ // When reading encoded Unicode, we'd expect to require
+ // catching MalformedInput
+ throw new RACFMalformedInputException(bbuf.position(),
+ bbuf.get(bbuf.position()),
+ cset.name());
+ if (r.isUnmappable())
+ // Since we're mapping TO unicode, we'd expect to be able
+ // to map all characters
+ Debug.assertTrue(false);
+ if (CoderResult.OVERFLOW == r)
+ Debug.assertTrue(false);
}
if (cbuf.remaining() == len) {
return -1;
@@ -387,7 +403,8 @@
}
}
- private final void encodeAndWrite(CharBuffer cbuf, boolean flush, boolean endOfFile) throws IOException {
+ private final void encodeAndWrite(CharBuffer cbuf, boolean flush,
+ boolean endOfFile) throws IOException {
while (cbuf.remaining() > 0) {
CoderResult r = cenc.encode(cbuf, bbuf, endOfFile);
bbufIsDirty = true;
@@ -395,6 +412,20 @@
flushBbuf(false);
bbuf.clear();
}
+ if (r.isUnmappable()) {
+ throw new RACFUnmappableCharacterException(cbuf.position(),
+ cbuf.charAt(cbuf.position()),
+ cset.name());
+ }
+ if (r.isMalformed()) {
+ // We don't really expect Malformed, but not handling it
+ // will cause an infinite loop if we don't...
+ throw new RACFMalformedInputException(cbuf.position(),
+ cbuf.charAt(cbuf.position()),
+ cset.name());
+ }
+ if (CoderResult.UNDERFLOW == r)
+ Debug.assertTrue(false);
}
if (bbuf.position() > 0 && bbufIsDirty && flush) {
flushBbuf(false);
More information about the armedbear-cvs
mailing list