enjoy 3.3 release ^_^
This commit is contained in:
122
src/main/java/com/jfinal/template/io/ByteWriter.java
Normal file
122
src/main/java/com/jfinal/template/io/ByteWriter.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
117
src/main/java/com/jfinal/template/io/CharWriter.java
Normal file
117
src/main/java/com/jfinal/template/io/CharWriter.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
44
src/main/java/com/jfinal/template/io/DateFormats.java
Normal file
44
src/main/java/com/jfinal/template/io/DateFormats.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
28
src/main/java/com/jfinal/template/io/Encoder.java
Normal file
28
src/main/java/com/jfinal/template/io/Encoder.java
Normal 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);
|
||||
}
|
||||
|
44
src/main/java/com/jfinal/template/io/EncoderFactory.java
Normal file
44
src/main/java/com/jfinal/template/io/EncoderFactory.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
120
src/main/java/com/jfinal/template/io/FastStringWriter.java
Normal file
120
src/main/java/com/jfinal/template/io/FastStringWriter.java
Normal 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 改造而来,在其基础之上做了如下改变:
|
||||
* 1:StringBuffer 属性改为 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
1306
src/main/java/com/jfinal/template/io/FloatingDecimal.java
Normal file
1306
src/main/java/com/jfinal/template/io/FloatingDecimal.java
Normal file
File diff suppressed because it is too large
Load Diff
67
src/main/java/com/jfinal/template/io/FloatingWriter.java
Normal file
67
src/main/java/com/jfinal/template/io/FloatingWriter.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
38
src/main/java/com/jfinal/template/io/IWritable.java
Normal file
38
src/main/java/com/jfinal/template/io/IWritable.java
Normal 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();
|
||||
}
|
||||
|
||||
|
||||
|
126
src/main/java/com/jfinal/template/io/IntegerWriter.java
Normal file
126
src/main/java/com/jfinal/template/io/IntegerWriter.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
65
src/main/java/com/jfinal/template/io/JdkEncoder.java
Normal file
65
src/main/java/com/jfinal/template/io/JdkEncoder.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
105
src/main/java/com/jfinal/template/io/LongWriter.java
Normal file
105
src/main/java/com/jfinal/template/io/LongWriter.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
98
src/main/java/com/jfinal/template/io/Utf8Encoder.java
Normal file
98
src/main/java/com/jfinal/template/io/Utf8Encoder.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
68
src/main/java/com/jfinal/template/io/Writer.java
Normal file
68
src/main/java/com/jfinal/template/io/Writer.java
Normal 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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
86
src/main/java/com/jfinal/template/io/WriterBuffer.java
Normal file
86
src/main/java/com/jfinal/template/io/WriterBuffer.java
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user