19f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/* 29f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Licensed to the Apache Software Foundation (ASF) under one 39f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * or more contributor license agreements. See the NOTICE file 49f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed with this work for additional information 59f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * regarding copyright ownership. The ASF licenses this file 69f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * to you under the Apache License, Version 2.0 (the "License"); 79f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * you may not use this file except in compliance with the License. 89f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * You may obtain a copy of the License at 99f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unless required by applicable law or agreed to in writing, software 139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * See the License for the specific language governing permissions and 169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * limitations under the License. 179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/* 199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * $Id: WriterToUTF8Buffered.java 469356 2006-10-31 03:20:34Z minchau $ 209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonpackage org.apache.xml.serializer; 229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.io.IOException; 249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.io.OutputStream; 259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.io.UnsupportedEncodingException; 269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonimport java.io.Writer; 279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson/** 309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This class writes unicode characters to a byte stream (java.io.OutputStream) 319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * as quickly as possible. It buffers the output in an internal 329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * buffer which must be flushed to the OutputStream when done. This flushing 339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * is done via the close() flush() or flushBuffer() method. 349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This class is only used internally within Xalan. 369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @xsl.usage internal 389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilsonfinal class WriterToUTF8Buffered extends Writer implements WriterChain 409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson{ 419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** number of bytes that the byte buffer can hold. 439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This is a fixed constant is used rather than m_outputBytes.lenght for performance. 449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private static final int BYTES_MAX=16*1024; 469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** number of characters that the character buffer can hold. 479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * This is 1/3 of the number of bytes because UTF-8 encoding 489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * can expand one unicode character by up to 3 bytes. 499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private static final int CHARS_MAX=(BYTES_MAX/3); 519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // private static final int 539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** The byte stream to write to. (sc & sb remove final to compile in JDK 1.1.8) */ 559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private final OutputStream m_os; 569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The internal buffer where data is stored. 599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * (sc & sb remove final to compile in JDK 1.1.8) 609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private final byte m_outputBytes[]; 629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private final char m_inputChars[]; 649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The number of valid bytes in the buffer. This value is always 679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * in the range <tt>0</tt> through <tt>m_outputBytes.length</tt>; elements 689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <tt>m_outputBytes[0]</tt> through <tt>m_outputBytes[count-1]</tt> contain valid 699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * byte data. 709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson private int count; 729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Create an buffered UTF-8 writer. 759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param out the underlying output stream. 789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @throws UnsupportedEncodingException 809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public WriterToUTF8Buffered(OutputStream out) 829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_os = out; 849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // get 3 extra bytes to make buffer overflow checking simpler and faster 859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // we won't have to keep checking for a few extra characters 869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_outputBytes = new byte[BYTES_MAX + 3]; 879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Big enough to hold the input chars that will be transformed 899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // into output bytes in m_ouputBytes. 909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_inputChars = new char[CHARS_MAX + 2]; 919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson count = 0; 929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// the old body of this constructor, before the buffersize was changed to a constant 949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// this(out, 8*1024); 959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Create an buffered UTF-8 writer to write data to the 999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * specified underlying output stream with the specified buffer 1009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * size. 1019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param out the underlying output stream. 1039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param size the buffer size. 1049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @exception IllegalArgumentException if size <= 0. 1059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// public WriterToUTF8Buffered(final OutputStream out, final int size) 1079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// { 1089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// 1099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// m_os = out; 1109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// 1119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// if (size <= 0) 1129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// { 1139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// throw new IllegalArgumentException( 1149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// SerializerMessages.createMessage(SerializerErrorResources.ER_BUFFER_SIZE_LESSTHAN_ZERO, null)); //"Buffer size <= 0"); 1159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// } 1169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// 1179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// m_outputBytes = new byte[size]; 1189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// count = 0; 1199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson// } 1209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 1229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Write a single character. The character to be written is contained in 1239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * the 16 low-order bits of the given integer value; the 16 high-order bits 1249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * are ignored. 1259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * <p> Subclasses that intend to support efficient single-character output 1279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * should override this method. 1289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param c int specifying a character to be written. 1309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @exception IOException If an I/O error occurs 1319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public void write(final int c) throws IOException 1339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /* If we are close to the end of the buffer then flush it. 1369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Remember the buffer can hold a few more bytes than BYTES_MAX 1379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (count >= BYTES_MAX) 1399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson flushBuffer(); 1409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (c < 0x80) 1429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_outputBytes[count++] = (byte) (c); 1449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else if (c < 0x800) 1469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_outputBytes[count++] = (byte) (0xc0 + (c >> 6)); 1489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_outputBytes[count++] = (byte) (0x80 + (c & 0x3f)); 1499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else if (c < 0x10000) 1519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_outputBytes[count++] = (byte) (0xe0 + (c >> 12)); 1539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_outputBytes[count++] = (byte) (0x80 + ((c >> 6) & 0x3f)); 1549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_outputBytes[count++] = (byte) (0x80 + (c & 0x3f)); 1559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 1579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_outputBytes[count++] = (byte) (0xf0 + (c >> 18)); 1599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_outputBytes[count++] = (byte) (0x80 + ((c >> 12) & 0x3f)); 1609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_outputBytes[count++] = (byte) (0x80 + ((c >> 6) & 0x3f)); 1619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_outputBytes[count++] = (byte) (0x80 + (c & 0x3f)); 1629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 1659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 1689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Write a portion of an array of characters. 1699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param chars Array of characters 1719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param start Offset from which to start writing characters 1729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param length Number of characters to write 1739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @exception IOException If an I/O error occurs 1759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 1769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @throws java.io.IOException 1779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 1789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public void write(final char chars[], final int start, final int length) 1799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson throws java.io.IOException 1809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // We multiply the length by three since this is the maximum length 1839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // of the characters that we can put into the buffer. It is possible 1849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // for each Unicode character to expand to three bytes. 1859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int lengthx3 = 3*length; 1879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (lengthx3 >= BYTES_MAX - count) 1899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // The requested length is greater than the unused part of the buffer 1919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson flushBuffer(); 1929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 1939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (lengthx3 > BYTES_MAX) 1949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 1959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /* 1969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The requested length exceeds the size of the buffer. 1979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Cut the buffer up into chunks, each of which will 1989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * not cause an overflow to the output buffer m_outputBytes, 1999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * and make multiple recursive calls. 2009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Be careful about integer overflows in multiplication. 2019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 2029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int split = length/CHARS_MAX; 2039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final int chunks; 2049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (length % CHARS_MAX > 0) 2059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson chunks = split + 1; 2069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 2079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson chunks = split; 2089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int end_chunk = start; 2099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (int chunk = 1; chunk <= chunks; chunk++) 2109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int start_chunk = end_chunk; 2129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson end_chunk = start + (int) ((((long) length) * chunk) / chunks); 2139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Adjust the end of the chunk if it ends on a high char 2159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // of a Unicode surrogate pair and low char of the pair 2169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // is not going to be in the same chunk 2179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final char c = chars[end_chunk - 1]; 2189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int ic = chars[end_chunk - 1]; 2199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (c >= 0xD800 && c <= 0xDBFF) { 2209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // The last Java char that we were going 2219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // to process is the first of a 2229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Java surrogate char pair that 2239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // represent a Unicode character. 2249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (end_chunk < start + length) { 2269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Avoid spanning by including the low 2279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // char in the current chunk of chars. 2289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson end_chunk++; 2299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } else { 2309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /* This is the last char of the last chunk, 2319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * and it is the high char of a high/low pair with 2329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * no low char provided. 2339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * TODO: error message needed. 2349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The char array incorrectly ends in a high char 2359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * of a high/low surrogate pair, but there is 2369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * no corresponding low as the high is the last char 2379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 2389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson end_chunk--; 2399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int len_chunk = (end_chunk - start_chunk); 2449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson this.write(chars,start_chunk, len_chunk); 2459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return; 2479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final int n = length+start; 2539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final byte[] buf_loc = m_outputBytes; // local reference for faster access 2549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int count_loc = count; // local integer for faster access 2559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int i = start; 2569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /* This block could be omitted and the code would produce 2589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * the same result. But this block exists to give the JIT 2599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * a better chance of optimizing a tight and common loop which 2609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * occurs when writing out ASCII characters. 2619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 2629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson char c; 2639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(; i < n && (c = chars[i])< 0x80 ; i++ ) 2649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte)c; 2659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (; i < n; i++) 2679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final char c = chars[i]; 2709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (c < 0x80) 2729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (c); 2739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else if (c < 0x800) 2749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0xc0 + (c >> 6)); 2769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 + (c & 0x3f)); 2779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 2799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The following else if condition is added to support XML 1.1 Characters for 2809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * UTF-8: [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]* 2819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unicode: [1101 10ww] [wwzz zzyy] (high surrogate) 2829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * [1101 11yy] [yyxx xxxx] (low surrogate) 2839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * * uuuuu = wwww + 1 2849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 2859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else if (c >= 0xD800 && c <= 0xDBFF) 2869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson char high, low; 2889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson high = c; 2899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson i++; 2909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson low = chars[i]; 2919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 2929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0xF0 | (((high + 0x40) >> 8) & 0xf0)); 2939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 | (((high + 0x40) >> 2) & 0x3f)); 2949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 | ((low >> 6) & 0x0f) + ((high << 4) & 0x30)); 2959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 | (low & 0x3f)); 2969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 2979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 2989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 2999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0xe0 + (c >> 12)); 3009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 + ((c >> 6) & 0x3f)); 3019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 + (c & 0x3f)); 3029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Store the local integer back into the instance variable 3059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson count = count_loc; 3069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 3109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Write a string. 3119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 3129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @param s String to be written 3139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 3149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @exception IOException If an I/O error occurs 3159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 3169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public void write(final String s) throws IOException 3179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // We multiply the length by three since this is the maximum length 3209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // of the characters that we can put into the buffer. It is possible 3219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // for each Unicode character to expand to three bytes. 3229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final int length = s.length(); 3239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int lengthx3 = 3*length; 3249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (lengthx3 >= BYTES_MAX - count) 3269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // The requested length is greater than the unused part of the buffer 3289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson flushBuffer(); 3299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (lengthx3 > BYTES_MAX) 3319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /* 3339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The requested length exceeds the size of the buffer, 3349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * so break it up in chunks that don't exceed the buffer size. 3359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 3369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final int start = 0; 3379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int split = length/CHARS_MAX; 3389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final int chunks; 3399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (length % CHARS_MAX > 0) 3409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson chunks = split + 1; 3419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 3429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson chunks = split; 3439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int end_chunk = 0; 3449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (int chunk = 1; chunk <= chunks; chunk++) 3459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int start_chunk = end_chunk; 3479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson end_chunk = start + (int) ((((long) length) * chunk) / chunks); 3489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson s.getChars(start_chunk,end_chunk, m_inputChars,0); 3499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int len_chunk = (end_chunk - start_chunk); 3509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Adjust the end of the chunk if it ends on a high char 3529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // of a Unicode surrogate pair and low char of the pair 3539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // is not going to be in the same chunk 3549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final char c = m_inputChars[len_chunk - 1]; 3559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (c >= 0xD800 && c <= 0xDBFF) { 3569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Exclude char in this chunk, 3579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // to avoid spanning a Unicode character 3589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // that is in two Java chars as a high/low surrogate 3599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson end_chunk--; 3609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson len_chunk--; 3619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (chunk == chunks) { 3629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /* TODO: error message needed. 3639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The String incorrectly ends in a high char 3649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * of a high/low surrogate pair, but there is 3659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * no corresponding low as the high is the last char 3669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Recover by ignoring this last char. 3679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 3689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson this.write(m_inputChars,0, len_chunk); 3729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return; 3749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson s.getChars(0, length , m_inputChars, 0); 3799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final char[] chars = m_inputChars; 3809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final int n = length; 3819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final byte[] buf_loc = m_outputBytes; // local reference for faster access 3829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int count_loc = count; // local integer for faster access 3839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson int i = 0; 3849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /* This block could be omitted and the code would produce 3869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * the same result. But this block exists to give the JIT 3879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * a better chance of optimizing a tight and common loop which 3889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * occurs when writing out ASCII characters. 3899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 3909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson char c; 3919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for(; i < n && (c = chars[i])< 0x80 ; i++ ) 3929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte)c; 3939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 3949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson for (; i < n; i++) 3959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 3969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson final char c = chars[i]; 3989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 3999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (c < 0x80) 4009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (c); 4019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else if (c < 0x800) 4029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4039f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0xc0 + (c >> 6)); 4049f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 + (c & 0x3f)); 4059f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4069f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 4079f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * The following else if condition is added to support XML 1.1 Characters for 4089f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * UTF-8: [1111 0uuu] [10uu zzzz] [10yy yyyy] [10xx xxxx]* 4099f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Unicode: [1101 10ww] [wwzz zzyy] (high surrogate) 4109f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * [1101 11yy] [yyxx xxxx] (low surrogate) 4119f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * * uuuuu = wwww + 1 4129f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4139f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else if (c >= 0xD800 && c <= 0xDBFF) 4149f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4159f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson char high, low; 4169f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson high = c; 4179f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson i++; 4189f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson low = chars[i]; 4199f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4209f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0xF0 | (((high + 0x40) >> 8) & 0xf0)); 4219f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 | (((high + 0x40) >> 2) & 0x3f)); 4229f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 | ((low >> 6) & 0x0f) + ((high << 4) & 0x30)); 4239f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 | (low & 0x3f)); 4249f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4259f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson else 4269f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4279f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0xe0 + (c >> 12)); 4289f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 + ((c >> 6) & 0x3f)); 4299f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson buf_loc[count_loc++] = (byte) (0x80 + (c & 0x3f)); 4309f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4319f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4329f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Store the local integer back into the instance variable 4339f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson count = count_loc; 4349f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4359f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4369f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4379f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 4389f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Flush the internal buffer 4399f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 4409f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @throws IOException 4419f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4429f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public void flushBuffer() throws IOException 4439f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4449f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4459f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson if (count > 0) 4469f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4479f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_os.write(m_outputBytes, 0, count); 4489f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4499f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson count = 0; 4509f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4519f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4529f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4539f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 4549f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Flush the stream. If the stream has saved any characters from the 4559f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * various write() methods in a buffer, write them immediately to their 4569f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * intended destination. Then, if that destination is another character or 4579f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * byte stream, flush it. Thus one flush() invocation will flush all the 4589f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * buffers in a chain of Writers and OutputStreams. 4599f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 4609f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @exception IOException If an I/O error occurs 4619f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 4629f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @throws java.io.IOException 4639f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4649f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public void flush() throws java.io.IOException 4659f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4669f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson flushBuffer(); 4679f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_os.flush(); 4689f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4699f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4709f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 4719f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Close the stream, flushing it first. Once a stream has been closed, 4729f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * further write() or flush() invocations will cause an IOException to be 4739f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * thrown. Closing a previously-closed stream, however, has no effect. 4749f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 4759f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @exception IOException If an I/O error occurs 4769f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 4779f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @throws java.io.IOException 4789f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4799f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public void close() throws java.io.IOException 4809f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4819f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson flushBuffer(); 4829f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson m_os.close(); 4839f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4849f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4859f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson /** 4869f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * Get the output stream where the events will be serialized to. 4879f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * 4889f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * @return reference to the result stream, or null of only a writer was 4899f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson * set. 4909f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson */ 4919f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public OutputStream getOutputStream() 4929f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4939f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return m_os; 4949f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 4959f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson 4969f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson public Writer getWriter() 4979f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson { 4989f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // Only one of getWriter() or getOutputStream() can return null 4999f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson // This type of writer wraps an OutputStream, not a Writer. 5009f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson return null; 5019f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson } 5029f8118474e9513f7a5b7d2a05e4a0fb15d1a6569Jesse Wilson} 503