enjoy 3.3 release ^_^

This commit is contained in:
James
2017-11-21 22:43:34 +08:00
parent 28eb105ffa
commit 61aa1d2082
70 changed files with 3378 additions and 299 deletions

View File

@@ -0,0 +1,122 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
import java.io.IOException;
import java.io.OutputStream;
/**
* ByteWriter
*/
public class ByteWriter extends Writer {
OutputStream out;
Encoder encoder;
char[] chars;
byte[] bytes;
public ByteWriter(Encoder encoder, int bufferSize) {
this.encoder = encoder;
this.chars = new char[bufferSize];
this.bytes = new byte[bufferSize * ((int)encoder.maxBytesPerChar())];
}
public ByteWriter init(OutputStream outputStream) {
this.out = outputStream;
return this;
}
public void flush() throws IOException {
out.flush();
}
public void close() {
try {
if (out != null) {
out.flush();
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
out = null;
}
}
public void write(String str, int offset, int len) throws IOException {
while (len > chars.length) {
write(str, offset, chars.length);
offset += chars.length;
len -= chars.length;
}
str.getChars(offset, offset + len, chars, 0);
int byteLen = encoder.encode(chars, 0, len, bytes);
out.write(bytes, 0, byteLen);
}
public void write(String str) throws IOException {
write(str, 0, str.length());
}
public void write(StringBuilder stringBuilder, int offset, int len) throws IOException {
while (len > chars.length) {
write(stringBuilder, offset, chars.length);
offset += chars.length;
len -= chars.length;
}
stringBuilder.getChars(offset, offset + len, chars, 0);
int byteLen = encoder.encode(chars, 0, len, bytes);
out.write(bytes, 0, byteLen);
}
public void write(StringBuilder stringBuilder) throws IOException {
write(stringBuilder, 0, stringBuilder.length());
}
public void write(IWritable writable) throws IOException {
byte[] data = writable.getBytes();
out.write(data, 0, data.length);
}
public void write(int intValue) throws IOException {
IntegerWriter.write(this, intValue);
}
public void write(long longValue) throws IOException {
LongWriter.write(this, longValue);
}
public void write(double doubleValue) throws IOException {
FloatingWriter.write(this, doubleValue);
}
public void write(float floatValue) throws IOException {
FloatingWriter.write(this, floatValue);
}
private static final byte[] TRUE_BYTES = "true".getBytes();
private static final byte[] FALSE_BYTES = "false".getBytes();
public void write(boolean booleanValue) throws IOException {
out.write(booleanValue ? TRUE_BYTES : FALSE_BYTES);
}
}

View File

@@ -0,0 +1,117 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
import java.io.IOException;
/**
* CharWriter
*/
public class CharWriter extends Writer {
java.io.Writer out;
char[] chars;
public CharWriter(int bufferSize) {
this.chars = new char[bufferSize];
}
public CharWriter init(java.io.Writer writer) {
this.out = writer;
return this;
}
public void flush() throws IOException {
out.flush();
}
public void close() {
try {
if (out != null) {
out.flush();
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
out = null;
}
}
public void write(String str, int offset, int len) throws IOException {
while (len > chars.length) {
write(str, offset, chars.length);
offset += chars.length;
len -= chars.length;
}
str.getChars(offset, offset + len, chars, 0);
out.write(chars, 0, len);
}
public void write(String str) throws IOException {
write(str, 0, str.length());
}
public void write(StringBuilder stringBuilder, int offset, int len) throws IOException {
while (len > chars.length) {
write(stringBuilder, offset, chars.length);
offset += chars.length;
len -= chars.length;
}
stringBuilder.getChars(offset, offset + len, chars, 0);
out.write(chars, 0, len);
}
public void write(StringBuilder stringBuilder) throws IOException {
write(stringBuilder, 0, stringBuilder.length());
}
public void write(IWritable writable) throws IOException {
char[] data = writable.getChars();
out.write(data, 0, data.length);
}
public void write(int intValue) throws IOException {
IntegerWriter.write(this, intValue);
}
public void write(long longValue) throws IOException {
LongWriter.write(this, longValue);
}
public void write(double doubleValue) throws IOException {
FloatingWriter.write(this, doubleValue);
}
public void write(float floatValue) throws IOException {
FloatingWriter.write(this, floatValue);
}
private static final char[] TRUE_CHARS = "true".toCharArray();
private static final char[] FALSE_CHARS = "false".toCharArray();
public void write(boolean booleanValue) throws IOException {
out.write(booleanValue ? TRUE_CHARS : FALSE_CHARS);
}
}

View File

@@ -0,0 +1,44 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
/**
* DateFormats
*/
public class DateFormats {
private Map<String, SimpleDateFormat> map = new HashMap<String, SimpleDateFormat>();
public SimpleDateFormat getDateFormat(String datePattern) {
SimpleDateFormat ret = map.get(datePattern);
if (ret == null) {
ret = new SimpleDateFormat(datePattern);
map.put(datePattern, ret);
}
return ret;
}
}

View File

@@ -0,0 +1,28 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
/**
* Encoder
*/
public abstract class Encoder {
public abstract float maxBytesPerChar();
public abstract int encode(char[] chars, int offset, int len, byte[] bytes);
}

View File

@@ -0,0 +1,44 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
import java.nio.charset.Charset;
import com.jfinal.template.EngineConfig;
/**
* EncoderFactory
*/
public class EncoderFactory {
protected Charset charset = Charset.forName(EngineConfig.DEFAULT_ENCODING);
void setEncoding(String encoding) {
charset = Charset.forName(encoding);
}
public Encoder getEncoder() {
if (Charset.forName("UTF-8").equals(charset)) {
return Utf8Encoder.me;
} else {
return new JdkEncoder(charset);
}
}
}

View File

@@ -0,0 +1,120 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
import java.io.Writer;
/**
* FastStringWriter
*
* <pre>
* 由 JDK 中 StringWriter 改造而来,在其基础之上做了如下改变:
* 1StringBuffer 属性改为 StringBuilder避免了前者的 synchronized 操作
* 2添加了 MAX_SIZE 属性
* 3去掉了 close() 方法声明中的 throws IOException并添加了代码原先该方法中无任何代码
* </pre>
*/
public class FastStringWriter extends Writer {
private StringBuilder buf;
public FastStringWriter() {
buf = new StringBuilder();
}
public FastStringWriter(int initialSize) {
if (initialSize < 0) {
throw new IllegalArgumentException("Negative buffer size");
}
buf = new StringBuilder(initialSize);
}
public void write(int c) {
buf.append((char) c);
}
public void write(char cbuf[], int off, int len) {
if ((off < 0) || (off > cbuf.length) || (len < 0) ||
((off + len) > cbuf.length) || ((off + len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return;
}
buf.append(cbuf, off, len);
}
public void write(String str) {
buf.append(str);
}
public void write(String str, int off, int len) {
buf.append(str.substring(off, off + len));
}
public FastStringWriter append(CharSequence csq) {
if (csq == null) {
write("null");
} else {
write(csq.toString());
}
return this;
}
public FastStringWriter append(CharSequence csq, int start, int end) {
CharSequence cs = (csq == null ? "null" : csq);
write(cs.subSequence(start, end).toString());
return this;
}
public FastStringWriter append(char c) {
write(c);
return this;
}
public String toString() {
return buf.toString();
}
public StringBuilder getBuffer() {
return buf;
}
public void flush() {
}
static int MAX_SIZE = 1024 * 128;
/**
* 由 StringWriter.close() 改造而来,原先该方法中无任何代码 ,改造如下:
* 1去掉 throws IOException
* 2添加 buf 空间释放处理逻辑
* 3添加 buf.setLength(0),以便于配合 ThreadLocal 回收利用
*/
public void close() {
if (buf.length() > MAX_SIZE) {
buf = new StringBuilder(); // 释放空间占用过大的 buf
} else {
buf.setLength(0);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,67 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
import java.io.IOException;
/**
* FloatingWriter
*/
public class FloatingWriter {
public static void write(ByteWriter byteWriter, double doubleValue) throws IOException {
FloatingDecimal fd = new FloatingDecimal(doubleValue);
char[] chars = byteWriter.chars;
byte[] bytes = byteWriter.bytes;
int len = fd.getChars(chars);
for (int i=0; i<len; i++) {
bytes[i] = (byte)chars[i];
}
byteWriter.out.write(bytes, 0, len);
}
public static void write(ByteWriter byteWriter, float floatValue) throws IOException {
FloatingDecimal fd = new FloatingDecimal(floatValue);
char[] chars = byteWriter.chars;
byte[] bytes = byteWriter.bytes;
int len = fd.getChars(chars);
for (int i=0; i<len; i++) {
bytes[i] = (byte)chars[i];
}
byteWriter.out.write(bytes, 0, len);
}
public static void write(CharWriter charWriter, double doubleValue) throws IOException {
FloatingDecimal fd = new FloatingDecimal(doubleValue);
char[] chars = charWriter.chars;
int len = fd.getChars(chars);
charWriter.out.write(chars, 0, len);
}
public static void write(CharWriter charWriter, float floatValue) throws IOException {
FloatingDecimal fd = new FloatingDecimal(floatValue);
char[] chars = charWriter.chars;
int len = fd.getChars(chars);
charWriter.out.write(chars, 0, len);
}
}

View File

@@ -0,0 +1,38 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
/**
* IWritable 支持 OutputStream、Writer 双模式动态切换输出
*
* 详见 com.jfinal.template.stat.ast.Text 中的用法
*/
public interface IWritable {
/**
* 供 OutputStream 模式下的 ByteWrite 使用
*/
public byte[] getBytes();
/**
* 供 Writer 模式下的 CharWrite 使用
*/
public char[] getChars();
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*/
package com.jfinal.template.io;
import java.io.IOException;
public class IntegerWriter {
final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
99999999, 999999999, Integer.MAX_VALUE };
final static char [] DigitOnes = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
} ;
final static char [] DigitTens = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
} ;
final static char[] digits = {
'0' , '1' , '2' , '3' , '4' , '5' ,
'6' , '7' , '8' , '9' , 'a' , 'b' ,
'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
'o' , 'p' , 'q' , 'r' , 's' , 't' ,
'u' , 'v' , 'w' , 'x' , 'y' , 'z'
};
private static final byte[] minValueBytes = "-2147483648".getBytes();
private static final char[] minValueChars = "-2147483648".toCharArray();
public static void write(ByteWriter byteWriter, int i) throws IOException {
if (i == Integer.MIN_VALUE) {
byteWriter.out.write(minValueBytes, 0, minValueBytes.length);
return ;
}
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] chars = byteWriter.chars;
byte[] bytes = byteWriter.bytes;
getChars(i, size, chars);
// int len = Utf8Encoder.me.encode(chars, 0, size, bytes);
// byteWriter.out.write(bytes, 0, len);
for (int j=0; j<size; j++) {
bytes[j] = (byte)chars[j];
}
byteWriter.out.write(bytes, 0, size);
}
public static void write(CharWriter charWriter, int i) throws IOException {
if (i == Integer.MIN_VALUE) {
charWriter.out.write(minValueChars, 0, minValueChars.length);
return ;
}
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] chars = charWriter.chars;
getChars(i, size, chars);
charWriter.out.write(chars, 0, size);
}
static int stringSize(int x) {
for (int i=0; ; i++)
if (x <= sizeTable[i])
return i+1;
}
static void getChars(int i, int index, char[] buf) {
int q, r;
int charPos = index;
char sign = 0;
if (i < 0) {
sign = '-';
i = -i;
}
// Generate two digits per iteration
while (i >= 65536) {
q = i / 100;
// really: r = i - (q * 100);
r = i - ((q << 6) + (q << 5) + (q << 2));
i = q;
buf [--charPos] = DigitOnes[r];
buf [--charPos] = DigitTens[r];
}
// Fall thru to fast mode for smaller numbers
// assert(i <= 65536, i);
for (;;) {
q = (i * 52429) >>> (16+3);
r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...
buf [--charPos] = digits [r];
i = q;
if (i == 0) break;
}
if (sign != 0) {
buf [--charPos] = sign;
}
}
}

View File

@@ -0,0 +1,65 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
/**
* JdkEncoder
*/
public class JdkEncoder extends Encoder {
private CharsetEncoder ce;
public JdkEncoder(Charset charset) {
this.ce = charset.newEncoder();
}
public float maxBytesPerChar() {
return ce.maxBytesPerChar();
}
public int encode(char[] chars, int offset, int len, byte[] bytes) {
ce.reset();
ByteBuffer bb = ByteBuffer.wrap(bytes);
CharBuffer cb = CharBuffer.wrap(chars, offset, len);
try {
CoderResult cr = ce.encode(cb, bb, true);
if (!cr.isUnderflow())
cr.throwException();
cr = ce.flush(bb);
if (!cr.isUnderflow())
cr.throwException();
return bb.position();
} catch (CharacterCodingException x) {
// Substitution is always enabled,
// so this shouldn't happen
throw new RuntimeException("Encode error: " + x.getMessage(), x);
}
}
}

View File

@@ -0,0 +1,105 @@
/*
* Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*/
package com.jfinal.template.io;
import java.io.IOException;
public class LongWriter {
private static final byte[] minValueBytes = "-9223372036854775808".getBytes();
private static final char[] minValueChars = "-9223372036854775808".toCharArray();
public static void write(ByteWriter byteWriter, long value) throws IOException {
if (value == Long.MIN_VALUE) {
byteWriter.out.write(minValueBytes, 0, minValueBytes.length);
return ;
}
int size = (value < 0) ? stringSize(-value) + 1 : stringSize(value);
char[] chars = byteWriter.chars;
byte[] bytes = byteWriter.bytes;
getChars(value, size, chars);
// int len = Utf8Encoder.me.encode(chars, 0, size, bytes);
// byteWriter.out.write(bytes, 0, len);
for (int j=0; j<size; j++) {
bytes[j] = (byte)chars[j];
}
byteWriter.out.write(bytes, 0, size);
}
public static void write(CharWriter charWriter, long i) throws IOException {
if (i == Long.MIN_VALUE) {
charWriter.out.write(minValueChars, 0, minValueChars.length);
return ;
}
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] chars = charWriter.chars;
getChars(i, size, chars);
charWriter.out.write(chars, 0, size);
}
static int stringSize(long x) {
long p = 10;
for (int i=1; i<19; i++) {
if (x < p)
return i;
p = 10*p;
}
return 19;
}
static void getChars(long i, int index, char[] buf) {
long q;
int r;
int charPos = index;
char sign = 0;
if (i < 0) {
sign = '-';
i = -i;
}
// Get 2 digits/iteration using longs until quotient fits into an int
while (i > Integer.MAX_VALUE) {
q = i / 100;
// really: r = i - (q * 100);
r = (int)(i - ((q << 6) + (q << 5) + (q << 2)));
i = q;
buf[--charPos] = IntegerWriter.DigitOnes[r];
buf[--charPos] = IntegerWriter.DigitTens[r];
}
// Get 2 digits/iteration using ints
int q2;
int i2 = (int)i;
while (i2 >= 65536) {
q2 = i2 / 100;
// really: r = i2 - (q * 100);
r = i2 - ((q2 << 6) + (q2 << 5) + (q2 << 2));
i2 = q2;
buf[--charPos] = IntegerWriter.DigitOnes[r];
buf[--charPos] = IntegerWriter.DigitTens[r];
}
// Fall thru to fast mode for smaller numbers
// assert(i2 <= 65536, i2);
for (;;) {
q2 = (i2 * 52429) >>> (16+3);
r = i2 - ((q2 << 3) + (q2 << 1)); // r = i2-(q2*10) ...
buf[--charPos] = IntegerWriter.digits[r];
i2 = q2;
if (i2 == 0) break;
}
if (sign != 0) {
buf[--charPos] = sign;
}
}
}

View File

@@ -0,0 +1,98 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
import java.nio.charset.MalformedInputException;
/**
* Utf8Encoder
*
* http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/sun/nio/cs/UTF_8.java?av=f
* http://grepcode.com/search?query=ArrayEncoder&start=0&entity=type&n=
*/
public class Utf8Encoder extends Encoder {
public static final Utf8Encoder me = new Utf8Encoder();
public float maxBytesPerChar() {
return 3.0F;
}
public int encode(char[] chars, int offset, int len, byte[] bytes) {
int sl = offset + len;
int dp = 0;
int dlASCII = dp + Math.min(len, bytes.length);
// ASCII only optimized loop
while (dp < dlASCII && chars[offset] < '\u0080') {
bytes[dp++] = (byte) chars[offset++];
}
while (offset < sl) {
char c = chars[offset++];
if (c < 0x80) {
// Have at most seven bits
bytes[dp++] = (byte) c;
} else if (c < 0x800) {
// 2 bytes, 11 bits
bytes[dp++] = (byte) (0xc0 | (c >> 6));
bytes[dp++] = (byte) (0x80 | (c & 0x3f));
} else if (c >= '\uD800' && c < ('\uDFFF' + 1)) { //Character.isSurrogate(c) but 1.7
final int uc;
int ip = offset - 1;
if (Character.isHighSurrogate(c)) {
if (sl - ip < 2) {
uc = -1;
} else {
char d = chars[ip + 1];
if (Character.isLowSurrogate(d)) {
uc = Character.toCodePoint(c, d);
} else {
throw new RuntimeException("encode UTF8 error", new MalformedInputException(1));
}
}
} else {
if (Character.isLowSurrogate(c)) {
throw new RuntimeException("encode UTF8 error", new MalformedInputException(1));
} else {
uc = c;
}
}
if (uc < 0) {
bytes[dp++] = (byte) '?';
} else {
bytes[dp++] = (byte) (0xf0 | ((uc >> 18)));
bytes[dp++] = (byte) (0x80 | ((uc >> 12) & 0x3f));
bytes[dp++] = (byte) (0x80 | ((uc >> 6) & 0x3f));
bytes[dp++] = (byte) (0x80 | (uc & 0x3f));
offset++; // 2 chars
}
} else {
// 3 bytes, 16 bits
bytes[dp++] = (byte) (0xe0 | ((c >> 12)));
bytes[dp++] = (byte) (0x80 | ((c >> 6) & 0x3f));
bytes[dp++] = (byte) (0x80 | (c & 0x3f));
}
}
return dp;
}
}

View File

@@ -0,0 +1,68 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
import java.io.IOException;
import java.util.Date;
/**
* Writer
*/
public abstract class Writer {
protected DateFormats formats = new DateFormats();
public abstract void flush() throws IOException;
public abstract void close();
public abstract void write(IWritable writable) throws IOException;
public abstract void write(String string, int offset, int length) throws IOException;
public abstract void write(String string) throws IOException;
public abstract void write(StringBuilder stringBuilder, int offset, int length) throws IOException;
public abstract void write(StringBuilder stringBuilder) throws IOException;
public abstract void write(boolean booleanValue) throws IOException;
public abstract void write(int intValue) throws IOException;
public abstract void write(long longValue) throws IOException;
public abstract void write(double doubleValue) throws IOException;
public abstract void write(float floatValue) throws IOException;
public void write(short shortValue) throws IOException {
write((int)shortValue);
}
public void write(Date date, String datePattern) throws IOException {
String str = formats.getDateFormat(datePattern).format(date);
write(str, 0, str.length());
}
}

View File

@@ -0,0 +1,86 @@
/**
* Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jfinal.template.io;
/**
* WriterBuffer
*/
public class WriterBuffer {
private static final int MIN_BUFFER_SIZE = 64; // 缓冲区最小 64 字节
private static final int MAX_BUFFER_SIZE = 1024 * 1024 * 10; // 缓冲区最大 10M 字节
private int bufferSize = 2048; // 缓冲区大小
private EncoderFactory encoderFactory = new EncoderFactory();
private final ThreadLocal<ByteWriter> byteWriters = new ThreadLocal<ByteWriter>() {
protected ByteWriter initialValue() {
return new ByteWriter(encoderFactory.getEncoder(), bufferSize);
}
};
private final ThreadLocal<CharWriter> charWriters = new ThreadLocal<CharWriter>() {
protected CharWriter initialValue() {
return new CharWriter(bufferSize);
}
};
private final ThreadLocal<FastStringWriter> fastStringWriters = new ThreadLocal<FastStringWriter>() {
protected FastStringWriter initialValue() {
return new FastStringWriter();
}
};
public ByteWriter getByteWriter(java.io.OutputStream outputStream) {
return byteWriters.get().init(outputStream);
}
public CharWriter getCharWriter(java.io.Writer writer) {
return charWriters.get().init(writer);
}
public FastStringWriter getFastStringWriter() {
return fastStringWriters.get();
}
public void setBufferSize(int bufferSize) {
if (bufferSize < MIN_BUFFER_SIZE || bufferSize > MAX_BUFFER_SIZE) {
throw new IllegalArgumentException("bufferSize must between " + (MIN_BUFFER_SIZE-1) + " and " + (MAX_BUFFER_SIZE+1));
}
this.bufferSize = bufferSize;
}
public void setEncoderFactory(EncoderFactory encoderFactory) {
if (encoderFactory == null) {
throw new IllegalArgumentException("encoderFactory can not be null");
}
this.encoderFactory = encoderFactory;
}
public void setEncoding(String encoding) {
encoderFactory.setEncoding(encoding);
}
}