001/*
002 * Trident - A Multithreaded Server Alternative
003 * Copyright 2014 The TridentSDK Team
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018package net.tridentsdk.util;
019
020import com.google.common.base.Preconditions;
021
022import javax.annotation.concurrent.NotThreadSafe;
023import java.util.Arrays;
024
025@NotThreadSafe
026public final class NibbleArray {
027    private final byte[] data;
028
029    public NibbleArray(int size) {
030        this(new byte[size / 2]);
031    }
032
033    public NibbleArray(byte... data) {
034        Preconditions.checkArgument(((data.length % 2) == 0), "Size must be even! Size is " + data.length);
035        this.data = data;
036    }
037
038    public byte[] array() {
039        return data;
040    }
041
042    public int length() {
043        return data.length * 2;
044    }
045
046    public int byteLength() {
047        return data.length;
048    }
049
050    public byte get(int index) {
051        return get(data, index);
052    }
053
054    public static void set(byte[] data, int index, byte value) {
055        value &= 0xF;
056        data[index / 2] &= (byte) (0xF << ((index + 1) % 2 * 4));
057        data[index / 2] |= (byte) (value << (index % 2 * 4));
058    }
059
060    public void fill(byte value) {
061        value &= 0xf;
062        Arrays.fill(data, (byte) ((value << 4) | value));
063    }
064
065    public void setRaw(byte[] source) {
066        Preconditions.checkArgument(data.length == source.length,
067                "Byte array length must be the same as current size!");
068        System.arraycopy(source, 0, data, 0, source.length);
069    }
070
071    public static byte get (byte[] source, int index) {
072        return (byte) (source[index / 2] >> ((index) % 2 * 4) & 0xF);
073    }
074}