001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: * Free SoftwareFoundation, Inc.
023: * 59 Temple Place, Suite 330
024: * Boston, MA 02111-1307 USA
025: *
026: * @author Scott Ferguson
027: */
028:
029: package com.caucho.vfs.i18n;
030:
031: import com.caucho.vfs.OutputStreamWithBuffer;
032:
033: import java.io.IOException;
034:
035: /**
036: * Implements an encoding char-to-byte writer for UTF8 and the associated
037: * factory.
038: */
039: public class UTF8Writer extends EncodingWriter {
040: private final static UTF8Writer _writer = new UTF8Writer();
041:
042: /**
043: * Null-arg constructor for instantiation by com.caucho.vfs.Encoding only.
044: */
045: public UTF8Writer() {
046: }
047:
048: /**
049: * Returns the Java encoding for the writer.
050: */
051: public String getJavaEncoding() {
052: return "UTF8";
053: }
054:
055: /**
056: * Returns the UTF8_Writer
057: *
058: * @return the UTF8_Writer
059: */
060: public EncodingWriter create(String javaEncoding) {
061: return _writer;
062: }
063:
064: /**
065: * Returns the UTF8_Writer
066: *
067: * @return the UTF8_Writer
068: */
069: public EncodingWriter create() {
070: return _writer;
071: }
072:
073: /**
074: * Writes a character to the output stream with the correct encoding.
075: *
076: * @param ch the character to write.
077: */
078: public void write(OutputStreamWithBuffer os, char ch)
079: throws IOException {
080: byte[] buffer = os.getBuffer();
081: int length = os.getBufferOffset();
082:
083: if (buffer.length <= length + 2) {
084: buffer = os.nextBuffer(length);
085: length = os.getBufferOffset();
086: }
087:
088: if (ch < 0x80) {
089: buffer[length++] = (byte) ch;
090: } else if (ch < 0x800) {
091: buffer[length++] = (byte) (0xc0 + (ch >> 6));
092: buffer[length++] = (byte) (0x80 + (ch & 0x3f));
093: } else {
094: buffer[length++] = (byte) (0xe0 + (ch >> 12));
095: buffer[length++] = (byte) (0x80 + ((ch >> 6) & 0x3f));
096: buffer[length++] = (byte) (0x80 + (ch & 0x3f));
097: }
098:
099: os.setBufferOffset(length);
100: }
101:
102: /**
103: * Writes into a character buffer using the correct encoding.
104: *
105: * @param cbuf character array with the data to write.
106: * @param off starting offset into the character array.
107: * @param len the number of characters to write.
108: */
109: public void write(OutputStreamWithBuffer os, char[] cbuf, int off,
110: int len) throws IOException {
111: byte[] buffer = os.getBuffer();
112: int length = os.getBufferOffset();
113: int capacity = buffer.length;
114:
115: for (int i = 0; i < len; i++) {
116: if (capacity <= length + 2) {
117: buffer = os.nextBuffer(length);
118: length = os.getBufferOffset();
119: }
120:
121: char ch = cbuf[off + i];
122:
123: if (ch < 0x80)
124: buffer[length++] = (byte) ch;
125: else if (ch < 0x800) {
126: buffer[length++] = (byte) (0xc0 + (ch >> 6));
127: buffer[length++] = (byte) (0x80 + (ch & 0x3f));
128: } else if (ch < 0xd800 || 0xdfff < ch) {
129: buffer[length++] = (byte) (0xe0 + (ch >> 12));
130: buffer[length++] = (byte) (0x80 + ((ch >> 6) & 0x3f));
131: buffer[length++] = (byte) (0x80 + (ch & 0x3f));
132: } else {
133: char ch2 = cbuf[off + i + 1];
134: int v = 0x10000 + (ch & 0x3ff) * 0x400 + (ch2 & 0x3ff);
135:
136: i += 1;
137:
138: buffer[length++] = (byte) (0xf0 + (v >> 18));
139: buffer[length++] = (byte) (0x80 + ((v >> 12) & 0x3f));
140: buffer[length++] = (byte) (0x80 + ((v >> 6) & 0x3f));
141: buffer[length++] = (byte) (0x80 + (v & 0x3f));
142: }
143: }
144:
145: os.setBufferOffset(length);
146: }
147: }
|