summaryrefslogtreecommitdiff
path: root/src/moe/anita/mai/buffer/MemBuf.java
blob: 922e624dccaffb932a18d69ea4a170b2fddd0bcb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package moe.anita.mai.buffer;

import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * An in-memory UTF-8 source buffer.
 *
 * Offsets and lengths are measured in UTF-8 bytes.
 */
public final class MemBuf implements Buffer {

	private final byte[] data;

	public MemBuf(String source) {
		Objects.requireNonNull(source);
		data = source.getBytes(StandardCharsets.UTF_8);
	}

	@Override
	public int length() {
		return data.length;
	}

	@Override
	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 new String(data, start, end - start, StandardCharsets.UTF_8);
	}
}