/* * Copyright 2011 Future Systems * * 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 org.krakenapps.btree.types; import java.nio.charset.Charset; public class KeyEncoder { private static final Charset UTF8 = Charset.forName("utf-8"); private KeyEncoder() { } public static byte[] encode(Object[] keys) { int length = 0; for (int i = 0; i < keys.length; i++) { Object item = keys[i]; if (item instanceof Integer) length += 4; else if (item instanceof Long) length += 8; else if (item instanceof String) length += 2 + ((String) item).getBytes(UTF8).length; } byte[] b = new byte[length]; int offset = 0; for (int i = 0; i < keys.length; i++) { Object item = keys[i]; if (item instanceof Integer) { encodeInt(b, offset, (Integer) item); offset += 4; } else if (item instanceof Long) { encodeLong(b, offset, (Long) item); offset += 8; } else if (item instanceof String) { offset += encodeString(b, offset, (String) item); } } return b; } public static Object[] decode(Class<?>[] keyTypes, byte[] b) { Object[] keys = new Object[keyTypes.length]; int i = 0; int offset = 0; for (Class<?> clazz : keyTypes) { if (clazz.equals(Integer.class)) { keys[i] = decodeInt(b, offset); offset += 4; } else if (clazz.equals(Long.class)) { keys[i] = decodeLong(b, offset); offset += 8; } else if (clazz.equals(String.class)) { int length = decodeStringLength(b, offset); keys[i] = new String(b, offset + 2, length, UTF8); offset += length + 2; } i++; } return keys; } public static void encodeInt(byte[] b, int offset, int l) { for (int i = 0; i < 4; i++) { b[offset + i] = (byte) ((l >> ((3 - i) * 8)) & 0xff); } } public static void encodeLong(byte[] b, int offset, long l) { for (int i = 0; i < 8; i++) { b[offset + i] = (byte) ((l >> ((7 - i) * 8)) & 0xff); } } public static int encodeString(byte[] b, int offset, String s) { byte[] sb = s.getBytes(UTF8); if (sb.length >= 0xffff) throw new IllegalArgumentException("string is too long: " + s); b[offset] = (byte) ((sb.length >> 8) & 0xff); b[offset + 1] = (byte) (sb.length & 0xff); for (int i = 0; i < sb.length; i++) b[offset + i + 2] = sb[i]; return sb.length + 2; } public static int decodeInt(byte[] b, int offset) { int l = 0; for (int i = 0; i < 4; i++) { l <<= 8; l |= b[offset + i] & 0xff; } return l; } public static long decodeLong(byte[] b, int offset) { int l = 0; for (int i = 0; i < 8; i++) { l <<= 8; l |= b[i + offset] & 0xff; } return l; } public static int decodeStringLength(byte[] b, int offset) { return (b[offset] << 8) | (b[offset + 1] & 0xff); } }