2 // ========================================================================
3 // Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
19 package org.eclipse.jetty.server;
21 import java.io.IOException;
24 * A writer that can wrap a {@link HttpOutput} stream and provide
25 * character encodings.
27 * The UTF-8 encoding is done by this class and no additional
28 * buffers or Writers are used.
29 * The UTF-8 code was inspired by http://javolution.org
31 public class Utf8HttpWriter extends HttpWriter
35 /* ------------------------------------------------------------ */
36 public Utf8HttpWriter(HttpOutput out)
41 /* ------------------------------------------------------------ */
43 public void write (char[] s,int offset, int length) throws IOException
45 HttpOutput out = _out;
46 if (length==0 && out.isAllContentWritten())
55 int chars = length>MAX_OUTPUT_CHARS?MAX_OUTPUT_CHARS:length;
57 byte[] buffer=_bytes.getBuf();
58 int bytes=_bytes.getCount();
60 if (bytes+chars>buffer.length)
61 chars=buffer.length-bytes;
63 for (int i = 0; i < chars; i++)
65 int code = s[offset+i];
67 // Do we already have a surrogate?
70 // No - is this char code a surrogate?
71 if(Character.isHighSurrogate((char)code))
73 _surrogate=code; // UCS-?
77 // else handle a low surrogate
78 else if(Character.isLowSurrogate((char)code))
80 code = Character.toCodePoint((char)_surrogate, (char)code); // UCS-4
85 code=_surrogate; // UCS-2
90 if ((code & 0xffffff80) == 0)
93 if (bytes>=buffer.length)
98 buffer[bytes++]=(byte)(code);
102 if((code&0xfffff800)==0)
105 if (bytes+2>buffer.length)
110 buffer[bytes++]=(byte)(0xc0|(code>>6));
111 buffer[bytes++]=(byte)(0x80|(code&0x3f));
113 else if((code&0xffff0000)==0)
116 if (bytes+3>buffer.length)
121 buffer[bytes++]=(byte)(0xe0|(code>>12));
122 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
123 buffer[bytes++]=(byte)(0x80|(code&0x3f));
125 else if((code&0xff200000)==0)
128 if (bytes+4>buffer.length)
133 buffer[bytes++]=(byte)(0xf0|(code>>18));
134 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
135 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
136 buffer[bytes++]=(byte)(0x80|(code&0x3f));
138 else if((code&0xf4000000)==0)
141 if (bytes+5>buffer.length)
146 buffer[bytes++]=(byte)(0xf8|(code>>24));
147 buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
148 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
149 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
150 buffer[bytes++]=(byte)(0x80|(code&0x3f));
152 else if((code&0x80000000)==0)
155 if (bytes+6>buffer.length)
160 buffer[bytes++]=(byte)(0xfc|(code>>30));
161 buffer[bytes++]=(byte)(0x80|((code>>24)&0x3f));
162 buffer[bytes++]=(byte)(0x80|((code>>18)&0x3f));
163 buffer[bytes++]=(byte)(0x80|((code>>12)&0x3f));
164 buffer[bytes++]=(byte)(0x80|((code>>6)&0x3f));
165 buffer[bytes++]=(byte)(0x80|(code&0x3f));
169 buffer[bytes++]=(byte)('?');
172 _surrogate=0; // USED
174 if (bytes==buffer.length)
181 _bytes.setCount(bytes);