Adds byte array to string converter

This commit is contained in:
konsoletyper 2013-12-20 15:02:52 +04:00
parent 97107a2953
commit 55218aba4b
7 changed files with 131 additions and 8 deletions

View File

@ -54,6 +54,10 @@ public class ByteBuffer {
return pos == end;
}
public void skip(int count) {
pos += count;
}
public byte get() {
return data[pos++];
}

View File

@ -34,7 +34,7 @@ public class UTF16Helper {
}
public static char lowSurrogate(int codePoint) {
return (char)(HIGH_SURROGATE_BITS | codePoint & SURROGATE_BIT_INV_MASK);
return (char)(LOW_SURROGATE_BITS | codePoint & SURROGATE_BIT_INV_MASK);
}
public static boolean isHighSurrogate(char c) {

View File

@ -53,6 +53,40 @@ public class UTF8Charset extends Charset {
@Override
public void decode(ByteBuffer source, CharBuffer dest) {
while (!source.end() && dest.available() >= 2) {
int b = source.get() & 0xFF;
if ((b & 0x80) == 0) {
dest.put((char)b);
} else if ((b & 0xE0) == 0xC0) {
if (source.end()) {
dest.put((char)b);
return;
}
dest.put((char)(((b & 0x1F) << 6) | (source.get() & 0x3F)));
} else if ((b & 0xF0) == 0xE0) {
if (source.available() < 2) {
source.skip(source.available());
dest.put((char)b);
return;
}
byte b2 = source.get();
byte b3 = source.get();
char c = (char)(((b & 0x0F) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3F));
dest.put(!UTF16Helper.isHighSurrogate(c) ? c : '?');
} else if ((b & 0xF8) == 0xF0) {
if (source.available() < 3) {
source.skip(source.available());
dest.put((char)b);
return;
}
byte b2 = source.get();
byte b3 = source.get();
byte b4 = source.get();
int code = (((b & 0x07) << 18) | ((b2 & 0x3f) << 12) | ((b3 & 0x3F) << 6) | (b4 & 0x3F)) -
UTF16Helper.SUPPLEMENTARY_PLANE;
dest.put(UTF16Helper.highSurrogate(code));
dest.put(UTF16Helper.lowSurrogate(code));
}
}
}
}

View File

@ -46,7 +46,7 @@ class TAbstractStringBuilder extends TObject implements TSerializable, TCharSequ
private static final int FLOAT_MAX_POS = 1000000;
private static final long DOUBLE_MAX_POS = 1000000000000000L;
char[] buffer;
int length;
private int length;
public TAbstractStringBuilder() {
this(16);
@ -490,6 +490,11 @@ class TAbstractStringBuilder extends TObject implements TSerializable, TCharSequ
return this;
}
protected TAbstractStringBuilder append(TObject obj) {
append(TString.wrap(obj != null ? obj.toString() : "null"));
return this;
}
private void ensureCapacity(int capacity) {
if (buffer.length >= capacity) {
return;
@ -522,7 +527,7 @@ class TAbstractStringBuilder extends TObject implements TSerializable, TCharSequ
return buffer[index];
}
public TAbstractStringBuilder append(TCharSequence s, int start, int end) {
protected TAbstractStringBuilder append(TCharSequence s, int start, int end) {
if (start > end || end > s.length() || start < 0) {
throw new TIndexOutOfBoundsException();
}
@ -533,10 +538,19 @@ class TAbstractStringBuilder extends TObject implements TSerializable, TCharSequ
return this;
}
public TAbstractStringBuilder append(TCharSequence s) {
protected TAbstractStringBuilder append(TCharSequence s) {
return append(s, 0, s.length());
}
protected TAbstractStringBuilder append(char[] chars, int offset, int len) {
ensureCapacity(length + len);
len += offset;
while (offset < len) {
buffer[length++] = chars[offset++];
}
return this;
}
@Override
public TCharSequence subSequence(int start, int end) {
// TODO: implement

View File

@ -15,8 +15,12 @@
*/
package org.teavm.classlib.java.lang;
import org.teavm.classlib.impl.charset.ByteBuffer;
import org.teavm.classlib.impl.charset.CharBuffer;
import org.teavm.classlib.impl.charset.Charset;
import org.teavm.classlib.impl.charset.UTF16Helper;
import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.io.TUnsupportedEncodingException;
import org.teavm.javascript.ni.GeneratedBy;
import org.teavm.javascript.ni.Rename;
@ -24,8 +28,7 @@ import org.teavm.javascript.ni.Rename;
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TString extends TObject implements TSerializable, TComparable<TString>,
TCharSequence {
public class TString extends TObject implements TSerializable, TComparable<TString>, TCharSequence {
private char[] characters;
private transient int hashCode;
@ -51,8 +54,43 @@ public class TString extends TObject implements TSerializable, TComparable<TStri
}
}
public TString(byte[] bytes, int offset, int length, TString charsetName) throws TUnsupportedEncodingException {
Charset charset = Charset.get(charsetName.toString());
if (charset == null) {
throw new TUnsupportedEncodingException(TString.wrap("Unknown encoding:" + charsetName));
}
initWithBytes(bytes, offset, length, charset);
}
public TString(byte[] bytes, int offset, int length) {
initWithBytes(bytes, offset, length, Charset.get("UTF-8"));
}
public TString(byte[] bytes) {
this(bytes, 0, bytes.length);
}
public TString(byte[] bytes, TString charsetName) throws TUnsupportedEncodingException {
this(bytes, 0, bytes.length, charsetName);
}
private void initWithBytes(byte[] bytes, int offset, int length, Charset charset) {
TStringBuilder sb = new TStringBuilder(bytes.length * 2);
this.characters = new char[sb.length()];
ByteBuffer source = new ByteBuffer(bytes, offset, offset + length);
char[] destChars = new char[TMath.max(8, TMath.min(length * 2, 1024))];
CharBuffer dest = new CharBuffer(destChars, 0, length * 2);
while (!source.end()) {
charset.decode(source, dest);
sb.append(destChars, 0, dest.position());
dest.rewind(0);
}
characters = new char[sb.length()];
sb.getChars(0, sb.length(), characters, 0);
}
public TString(TStringBuilder sb) {
this(sb.buffer, 0, sb.length);
this(sb.buffer, 0, sb.length());
}
@Override

View File

@ -20,6 +20,14 @@ package org.teavm.classlib.java.lang;
* @author Alexey Andreev
*/
public class TStringBuilder extends TAbstractStringBuilder {
public TStringBuilder(int capacity) {
super(capacity);
}
public TStringBuilder() {
super();
}
@Override
public TStringBuilder append(TString string) {
super.append(string);
@ -56,6 +64,12 @@ public class TStringBuilder extends TAbstractStringBuilder {
return this;
}
@Override
public TStringBuilder append(char[] chars, int offset, int len) {
super.append(chars, offset, len);
return this;
}
@Override
public TStringBuilder appendCodePoint(int codePoint) {
super.appendCodePoint(codePoint);
@ -73,4 +87,10 @@ public class TStringBuilder extends TAbstractStringBuilder {
super.append(s);
return this;
}
@Override
public TStringBuilder append(TObject obj) {
super.append(obj);
return this;
}
}

View File

@ -16,6 +16,7 @@
package org.teavm.classlib.java.lang;
import static org.junit.Assert.*;
import java.io.UnsupportedEncodingException;
import org.junit.Test;
/**
@ -205,4 +206,16 @@ public class StringTest {
assertEquals('2', array[1]);
assertEquals('3', array[2]);
}
@Test
public void createdFromByteArray() throws UnsupportedEncodingException {
byte[] bytes = { 49, 50, 51 };
assertEquals("123", new String(bytes, "UTF-8"));
}
@Test
public void createdFromUTF8ByteArray() throws UnsupportedEncodingException {
byte[] bytes = { 65, -62, -69, -32, -82, -69, -16, -66, -78, -69 };
assertEquals("A\u00BB\u0BBB\uD8BB\uDCBB", new String(bytes, "UTF-8"));
}
}