Skip to content

Commit

Permalink
fixed testcase & removed unused code
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed Apr 20, 2016
1 parent fc79e80 commit f5cf23e
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 141 deletions.
3 changes: 3 additions & 0 deletions src/main/java/com/alibaba/fastjson/JSON.java
Expand Up @@ -22,6 +22,7 @@
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.CharBuffer; import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetDecoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
Expand Down Expand Up @@ -62,6 +63,8 @@ public abstract class JSON implements JSONStreamAware, JSONAware {
public static int DEFAULT_PARSER_FEATURE; public static int DEFAULT_PARSER_FEATURE;


static final SerializeFilter[] emptyFilters = new SerializeFilter[0]; static final SerializeFilter[] emptyFilters = new SerializeFilter[0];

static Charset utf8 = Charset.forName("UTF-8");


// /** // /**
// * asm生成代码dump路径 // * asm生成代码dump路径
Expand Down
@@ -1,6 +1,5 @@
package com.alibaba.fastjson.serializer; package com.alibaba.fastjson.serializer;


import java.lang.ref.SoftReference;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.CharBuffer; import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException; import java.nio.charset.CharacterCodingException;
Expand All @@ -13,110 +12,61 @@


public class SerialWriterStringEncoder { public class SerialWriterStringEncoder {


private final CharsetEncoder encoder; private final CharsetEncoder encoder;

public SerialWriterStringEncoder(Charset cs){
this.encoder = cs.newEncoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE);
}

public byte[] encode(char[] chars, int off, int len) {
if (len == 0) {
return new byte[0];
}

encoder.reset();

// We need to perform double, not float, arithmetic; otherwise
// we lose low order bits when len is larger than 2**24.
int bytesLength = (int) (len * (double) encoder.maxBytesPerChar());
byte[] bytes = getBytes(bytesLength);

ByteBuffer byteBuf = ByteBuffer.wrap(bytes);

CharBuffer charBuf = CharBuffer.wrap(chars, off, len);
try {
CoderResult cr = encoder.encode(charBuf, byteBuf, true);
if (!cr.isUnderflow()) {
cr.throwException();
}
cr = encoder.flush(byteBuf);
if (!cr.isUnderflow()) {
cr.throwException();
}
} catch (CharacterCodingException x) {
// Substitution is always enabled,
// so this shouldn't happen
throw new JSONException(x.getMessage(), x);
}

int position = byteBuf.position();
byte[] copy = new byte[position];
System.arraycopy(bytes, 0, copy, 0, position);
return copy;
}

private final static ThreadLocal<byte[]> bytesBufLocal = new ThreadLocal<byte[]>();

public static byte[] getBytes(int length) {
byte[] bytes = bytesBufLocal.get();

if (bytes == null) {
bytes = new byte[1024 * 8];
bytesBufLocal.set(bytes);
}

return bytes.length < length //
? new byte[length] //
: bytes;
}


public SerialWriterStringEncoder(Charset cs) {
this(cs.newEncoder().onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE));
}

public SerialWriterStringEncoder(CharsetEncoder encoder) {
this.encoder = encoder;
}

public byte[] encode(char[] chars, int off, int len) {
if (len == 0) {
return new byte[0];
}

encoder.reset();

int bytesLength = scale(len, encoder.maxBytesPerChar());

byte[] bytes = getBytes(bytesLength);

return encode(chars, off, len, bytes);
}

public CharsetEncoder getEncoder() {
return encoder;
}

public byte[] encode(char[] chars, int off, int len, byte[] bytes) {
ByteBuffer byteBuf = ByteBuffer.wrap(bytes);

CharBuffer charBuf = CharBuffer.wrap(chars, off, len);
try {
CoderResult cr = encoder.encode(charBuf, byteBuf, true);
if (!cr.isUnderflow()) {
cr.throwException();
}
cr = encoder.flush(byteBuf);
if (!cr.isUnderflow()) {
cr.throwException();
}
} catch (CharacterCodingException x) {
// Substitution is always enabled,
// so this shouldn't happen
throw new JSONException(x.getMessage(), x);
}

int bytesLength = byteBuf.position();
byte[] copy = new byte[bytesLength];
System.arraycopy(bytes, 0, copy, 0, bytesLength);
return copy;
}

private static int scale(int len, float expansionFactor) {
// We need to perform double, not float, arithmetic; otherwise
// we lose low order bits when len is larger than 2**24.
return (int) (len * (double) expansionFactor);
}

private final static ThreadLocal<SoftReference<byte[]>> bytesBufLocal = new ThreadLocal<SoftReference<byte[]>>();

public static void clearBytes() {
bytesBufLocal.set(null);
}

public static byte[] getBytes(int length) {
SoftReference<byte[]> ref = bytesBufLocal.get();

if (ref == null) {
return allocateBytes(length);
}

byte[] bytes = ref.get();

if (bytes == null) {
return allocateBytes(length);
}

if (bytes.length < length) {
bytes = allocateBytes(length);
}

return bytes;
}

private static byte[] allocateBytes(int length) {
final int minExp = 10;
final int BYTES_CACH_MAX_SIZE = 1024 * 128; // 128k, 2^17;

if(length > BYTES_CACH_MAX_SIZE) {
return new byte[length];
}

int allocateLength;
{
int part = length >>> minExp;
if(part <= 0) {
allocateLength = 1<< minExp;
} else {
allocateLength = 1 << 32 - Integer.numberOfLeadingZeros(length-1);
}
}
byte[] chars = new byte[allocateLength];
bytesBufLocal.set(new SoftReference<byte[]>(chars));
return chars;
}
} }
@@ -1,43 +1,59 @@
package com.alibaba.json.bvt.serializer; package com.alibaba.json.bvt.serializer;


import java.lang.reflect.Field;
import java.nio.BufferOverflowException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;


import org.junit.Assert; import org.junit.Assert;
import junit.framework.TestCase;


import com.alibaba.fastjson.serializer.SerialWriterStringEncoder; import com.alibaba.fastjson.serializer.SerialWriterStringEncoder;


import junit.framework.TestCase;

public class SerialWriterStringEncoderTest extends TestCase { public class SerialWriterStringEncoderTest extends TestCase {


SerialWriterStringEncoder UTF8 = new SerialWriterStringEncoder(Charset.forName("UTF-8")); SerialWriterStringEncoder UTF8 = new SerialWriterStringEncoder(Charset.forName("UTF-8"));
SerialWriterStringEncoder ISO88591 = new SerialWriterStringEncoder(Charset.forName("ISO-8859-1")); SerialWriterStringEncoder ISO88591 = new SerialWriterStringEncoder(Charset.forName("ISO-8859-1"));

static Field field;
static {
try {
field = SerialWriterStringEncoder.class.getDeclaredField("encoder");
field.setAccessible(true);
} catch (Exception e) {
e.printStackTrace();
}
}


public void test_0() throws Exception { public void test_0() throws Exception {


Assert.assertEquals(0, UTF8.encode(new char[0], 0, 0).length); Assert.assertEquals(0, UTF8.encode(new char[0], 0, 0).length);
Assert.assertEquals(3, UTF8.encode(new char[] { 'a', 'b', 'c' }, 0, 3).length); Assert.assertEquals(3, UTF8.encode(new char[] { 'a', 'b', 'c' }, 0, 3).length);
} }


public void test_error_0() throws Exception { // public void test_error_0() throws Exception {
Exception error = null; // Exception error = null;
try { // try {
UTF8.getEncoder().reset(); // CharsetEncoder encoder = (CharsetEncoder) field.get(UTF8);
UTF8.encode(new char[] { 'a', 'b', 'c' }, 0, 3, new byte[0]); // encoder.reset();
} catch (Exception ex) { // UTF8.encode(new char[] { 'a', 'b', 'c' }, 0, 3, new byte[0]);
error = ex; // } catch (BufferOverflowException ex) {
} // error = ex;
Assert.assertNotNull(error); // }
} // Assert.assertNotNull(error);

// }
public void test_error_1() throws Exception {
Exception error = null; // public void test_error_1() throws Exception {
try { // Exception error = null;
UTF8.getEncoder().reset(); // try {
UTF8.encode(new char[] { '中', '国', '人' }, 0, 3, new byte[8]); // CharsetEncoder encoder = (CharsetEncoder) field.get(UTF8);
} catch (Exception ex) { // encoder.reset();
error = ex; // UTF8.encode(new char[] { '中', '国', '人' }, 0, 3, new byte[8]);
} // } catch (BufferOverflowException ex) {
Assert.assertNotNull(error); // error = ex;
} // }
// Assert.assertNotNull(error);
// }


} }
@@ -1,22 +1,27 @@
package com.alibaba.json.bvt.serializer; package com.alibaba.json.bvt.serializer;


import java.lang.reflect.Field;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.CharBuffer; import java.nio.CharBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder; import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult; import java.nio.charset.CoderResult;


import org.junit.Assert; import org.junit.Assert;
import junit.framework.TestCase;


import com.alibaba.fastjson.serializer.SerialWriterStringEncoder; import com.alibaba.fastjson.serializer.SerialWriterStringEncoder;


import junit.framework.TestCase;

public class SerialWriterStringEncoderTest2 extends TestCase { public class SerialWriterStringEncoderTest2 extends TestCase {


public void test_error_0() throws Exception { public void test_error_0() throws Exception {
Charset charset = Charset.forName("UTF-8"); Charset charset = Charset.forName("UTF-8");
CharsetEncoder charsetEncoder = new MockCharsetEncoder2(charset); CharsetEncoder charsetEncoder = new MockCharsetEncoder2(charset);
SerialWriterStringEncoder encoder = new SerialWriterStringEncoder(charsetEncoder); SerialWriterStringEncoder encoder = new SerialWriterStringEncoder(charset);
Field field = SerialWriterStringEncoder.class.getDeclaredField("encoder");
field.setAccessible(true);
field.set(encoder, charsetEncoder);


Exception error = null; Exception error = null;
char[] chars = "abc".toCharArray(); char[] chars = "abc".toCharArray();
Expand All @@ -31,8 +36,13 @@ public void test_error_0() throws Exception {
public void test_error_1() throws Exception { public void test_error_1() throws Exception {
Charset charset = Charset.forName("UTF-8"); Charset charset = Charset.forName("UTF-8");
CharsetEncoder realEncoder = charset.newEncoder(); CharsetEncoder realEncoder = charset.newEncoder();

SerialWriterStringEncoder encoder = new SerialWriterStringEncoder(charset);

CharsetEncoder charsetEncoder = new MockCharsetEncoder(charset, realEncoder); CharsetEncoder charsetEncoder = new MockCharsetEncoder(charset, realEncoder);
SerialWriterStringEncoder encoder = new SerialWriterStringEncoder(charsetEncoder); Field field = SerialWriterStringEncoder.class.getDeclaredField("encoder");
field.setAccessible(true);
field.set(encoder, charsetEncoder);


Exception error = null; Exception error = null;
char[] chars = "abc".toCharArray(); char[] chars = "abc".toCharArray();
Expand Down
31 changes: 21 additions & 10 deletions src/test/java/com/alibaba/json/bvt/util/ThreadLocalCacheTest.java
@@ -1,5 +1,7 @@
package com.alibaba.json.bvt.util; package com.alibaba.json.bvt.util;


import java.lang.reflect.Field;

import org.junit.Assert; import org.junit.Assert;


import com.alibaba.fastjson.serializer.SerialWriterStringEncoder; import com.alibaba.fastjson.serializer.SerialWriterStringEncoder;
Expand Down Expand Up @@ -29,19 +31,28 @@ public void test() throws Exception {


public void testBytes() throws Exception { public void testBytes() throws Exception {


SerialWriterStringEncoder.clearBytes(); clearBytes();
Assert.assertEquals(SerialWriterStringEncoder.getBytes(0).length, 1024); Assert.assertEquals(SerialWriterStringEncoder.getBytes(0).length, 8192);
Assert.assertEquals(SerialWriterStringEncoder.getBytes(1024).length, 1024); Assert.assertEquals(SerialWriterStringEncoder.getBytes(1024).length, 8192);
Assert.assertEquals(SerialWriterStringEncoder.getBytes(2048).length, 2048); Assert.assertEquals(SerialWriterStringEncoder.getBytes(8192 * 2).length, 8192 * 2);
Assert.assertEquals(SerialWriterStringEncoder.getBytes(0).length, 2048); Assert.assertEquals(SerialWriterStringEncoder.getBytes(0).length, 8192);
Assert.assertSame(SerialWriterStringEncoder.getBytes(0), SerialWriterStringEncoder.getBytes(1204));
Assert.assertNotSame(SerialWriterStringEncoder.getBytes(9000), SerialWriterStringEncoder.getBytes(9000));


SerialWriterStringEncoder.clearBytes(); clearBytes();
Assert.assertEquals(SerialWriterStringEncoder.getBytes(2048).length, 2048); Assert.assertEquals(SerialWriterStringEncoder.getBytes(2048).length, 8192);


SerialWriterStringEncoder.clearBytes(); clearBytes();
Assert.assertEquals(SerialWriterStringEncoder.getBytes(1024 * 256).length, 1024 * 256); Assert.assertEquals(SerialWriterStringEncoder.getBytes(1024 * 256).length, 1024 * 256);
Assert.assertEquals(SerialWriterStringEncoder.getBytes(0).length, 1024); Assert.assertEquals(SerialWriterStringEncoder.getBytes(0).length, 8192);
SerialWriterStringEncoder.clearBytes(); clearBytes();


} }

public static void clearBytes() throws Exception {
Field field = SerialWriterStringEncoder.class.getDeclaredField("bytesBufLocal");
field.setAccessible(true);
ThreadLocal<byte[]> bytesBufLocal = (ThreadLocal<byte[]>) field.get(null);
bytesBufLocal.set(null);
}
} }

0 comments on commit f5cf23e

Please sign in to comment.