diff options
Diffstat (limited to 'src/moe/anita/mai/buffer/MemBuf.java')
| -rw-r--r-- | src/moe/anita/mai/buffer/MemBuf.java | 57 |
1 files changed, 50 insertions, 7 deletions
diff --git a/src/moe/anita/mai/buffer/MemBuf.java b/src/moe/anita/mai/buffer/MemBuf.java index a2bc477..922e624 100644 --- a/src/moe/anita/mai/buffer/MemBuf.java +++ b/src/moe/anita/mai/buffer/MemBuf.java @@ -1,29 +1,72 @@ package moe.anita.mai.buffer; +import java.nio.charset.StandardCharsets; import java.util.Objects; /** - * Buffer backed entirely by an in-memory string. + * An in-memory UTF-8 source buffer. + * + * Offsets and lengths are measured in UTF-8 bytes. */ public final class MemBuf implements Buffer { - private final String data; + private final byte[] data; - public MemBuf(String data) { this.data = Objects.requireNonNull(data); + public MemBuf(String source) { + Objects.requireNonNull(source); + data = source.getBytes(StandardCharsets.UTF_8); } @Override public int length() { - return data.length(); + return data.length; } @Override - public char get(int index) { - return data.charAt(index); + public int get(int offset) { + int first = Byte.toUnsignedInt(data[offset]); + + if ((first & 0x80) == 0) { + return first; + } + + if ((first & 0xE0) == 0xC0) { + return ((first & 0x1F) << 6) | (Byte.toUnsignedInt(data[offset + 1]) & 0x3F); + } + + if ((first & 0xF0) == 0xE0) { + return ((first & 0x0F) << 12) + | ((Byte.toUnsignedInt(data[offset + 1]) & 0x3F) << 6) + | (Byte.toUnsignedInt(data[offset + 2]) & 0x3F); + } + + return ((first & 0x07) << 18) + | ((Byte.toUnsignedInt(data[offset + 1]) & 0x3F) << 12) + | ((Byte.toUnsignedInt(data[offset + 2]) & 0x3F) << 6) + | (Byte.toUnsignedInt(data[offset + 3]) & 0x3F); + } + + @Override + public int width(int offset) { + int first = Byte.toUnsignedInt(data[offset]); + + if ((first & 0x80) == 0) { + return 1; + } + + if ((first & 0xE0) == 0xC0) { + return 2; + } + + if ((first & 0xF0) == 0xE0) { + return 3; + } + + return 4; } @Override public CharSequence slice(int start, int end) { - return data.subSequence(start, end); + return new String(data, start, end - start, StandardCharsets.UTF_8); } } |
