<commit_before>/*
 * Copyright 2009-2011 <NAME>
 *
 * 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.ardverk.dht;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Random;

import org.ardverk.coding.CodingUtils;
import org.ardverk.collection.Key;
import org.ardverk.collection.KeyAnalyzer;
import org.ardverk.dht.lang.Identifier;
import org.ardverk.dht.lang.Negation;
import org.ardverk.dht.lang.Xor;
import org.ardverk.dht.security.SecurityUtils;
import org.ardverk.lang.ByteArray;


/**
 * Kademlia Unique Identifier ({@link KUID}) 
 */
public class KUID extends ByteArray<KUID> implements Identifier, 
        Key<KUID>, Xor<KUID>, Negation<KUID>, Cloneable {

    private static final long serialVersionUID = -4611363711131603626L;
    
    private static final Random GENERATOR 
        = SecurityUtils.createSecureRandom();
    
    private static final int MSB = 1 << Byte.SIZE-1;
    
    /**
     * Creates and returns a random {@link KUID} of the given length in bytes.
     */
    public static KUID createRandom(int length) {
        byte[] key = new byte[length];
        GENERATOR.nextBytes(key);
        return new KUID(key);
    }
    
    /**
     * Creates and returns a random {@link KUID} of the same 
     * length as the given {@link KUID}.
     */
    public static KUID createRandom(KUID otherId) {
        return createRandom(otherId.length());
    }
    
    /**
     * Creates and returns a {@link KUID} from the given bytes.
     */
    public static KUID create(byte[] key) {
        return new KUID(key);
    }
    
    /**
     * Creates and returns a {@link KUID} from the given bytes.
     */
    public static KUID create(byte[] key, int offset, int length) {
        byte[] copy = new byte[length];
        System.arraycopy(key, 0, copy, 0, copy.length);
        return new KUID(copy);
    }
    
    /**
     * Creates and returns a {@link KUID} from a string encoded key.
     */
    public static KUID create(String key, int radix) {
        switch (radix) {
            case 16:
                byte[] data = CodingUtils.decodeBase16(key);
                return create(data);
            default:
                throw new IllegalArgumentException("radix=" + radix);
        }
    }
    
    /**
     * Creates and returns a random {@link KUID} that has the same
     * prefix as the given {@link KUID}.
     * 
     * NOTE: The bitIndex is counted 0 through n and is inclusive.
     * If you want the first three (3) bits to be the same then
     * pass two (2) as an argument (0 through 2 inclusive is 3).
     */
    public static KUID createWithPrefix(KUID prefix, int bitIndex) {
        // 1) Create a random KUID of the same length
        byte[] dst = new byte[prefix.length()];
        GENERATOR.nextBytes(dst);
        
        // 2) Overwrite the prefix bytes
        ++bitIndex;
        int length = bitIndex/8;
        System.arraycopy(prefix.value, 0, dst, 0, length);
        
        // 3) Overwrite the remaining bits
        int bitsToCopy = bitIndex % 8;
        if (bitsToCopy != 0) {
            // Mask has the low-order (8-bits) bits set
            int mask = (1 << (8-bitsToCopy)) - 1;
            int prefixByte = prefix.value[length];
            int randByte   = dst[length];
            dst[length] = (byte) ((prefixByte & ~mask) | (randByte & mask));
        }
        
        return create(dst);
    }
    
    /**
     * Returns a minimum {@link KUID} of the given length.
     */
    public static KUID min(int length) {
        return new KUID(new byte[length]);
    }
    
    /**
     * Returns a maximum {@link KUID} of the given length.
     */
    public static KUID max(int length) {
        byte[] maxKey = new byte[length];
        Arrays.fill(maxKey, (byte)0xFF);
        return new KUID(maxKey);
    }
    
    private KUID(byte[] key) {
        super(key);
    }
    
    @Override
    public KUID getId() {
        return this;
    }

    /**
     * Returns {@code true} if the given {@link KUID} is compatible with
     * this {@link KUID}.
     */
    public boolean isCompatible(KUID otherId) {
        return otherId != null && length() == otherId.length();
    }
    
    /**
     * Calls {@link MessageDigest#update(byte[])} with the {@link KUID}'s bytes.
     */
    public void update(MessageDigest md) {
        md.update(value);
    }
    
    @Override
    public int lengthInBits() {
        return length() * Byte.SIZE;
    }
    
    @Override
    public boolean isBitSet(int bitIndex) {
        int index = (int)(bitIndex / Byte.SIZE);
        int bit = (int)(bitIndex % Byte.SIZE);
        return (value[index] & mask(bit)) != 0;
    }
    
    @Override
    public int bitIndex(KUID otherId) {
        if (!isCompatible(otherId)) {
            throw new IllegalArgumentException("otherKey=" + otherId);            
        }
        
        boolean allNull = true;
        for (int i = 0; i < value.length; i++) {
            byte b1 = value[i];<commit_msg>Ley KUID implement the Digestable interface<commit_after>/*
 * Copyright 2009-2011 <NAME>
 *
 * 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.ardverk.dht;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Random;

import org.ardverk.coding.CodingUtils;
import org.ardverk.collection.Key;
import org.ardverk.collection.KeyAnalyzer;
import org.ardverk.dht.lang.Identifier;
import org.ardverk.dht.lang.Negation;
import org.ardverk.dht.lang.Xor;
import org.ardverk.dht.security.SecurityUtils;
import org.ardverk.lang.ByteArray;
import org.ardverk.security.Digestable;


/**
 * Kademlia Unique Identifier ({@link KUID}) 
 */
public class KUID extends ByteArray<KUID> implements Identifier, 
        Key<KUID>, Xor<KUID>, Negation<KUID>, Cloneable, Digestable {

    private static final long serialVersionUID = -4611363711131603626L;
    
    private static final Random GENERATOR 
        = SecurityUtils.createSecureRandom();
    
    private static final int MSB = 1 << Byte.SIZE-1;
    
    /**
     * Creates and returns a random {@link KUID} of the given length in bytes.
     */
    public static KUID createRandom(int length) {
        byte[] key = new byte[length];
        GENERATOR.nextBytes(key);
        return new KUID(key);
    }
    
    /**
     * Creates and returns a random {@link KUID} of the same 
     * length as the given {@link KUID}.
     */
    public static KUID createRandom(KUID otherId) {
        return createRandom(otherId.length());
    }
    
    /**
     * Creates and returns a {@link KUID} from the given bytes.
     */
    public static KUID create(byte[] key) {
        return new KUID(key);
    }
    
    /**
     * Creates and returns a {@link KUID} from the given bytes.
     */
    public static KUID create(byte[] key, int offset, int length) {
        byte[] copy = new byte[length];
        System.arraycopy(key, 0, copy, 0, copy.length);
        return new KUID(copy);
    }
    
    /**
     * Creates and returns a {@link KUID} from a string encoded key.
     */
    public static KUID create(String key, int radix) {
        switch (radix) {
            case 16:
                byte[] data = CodingUtils.decodeBase16(key);
                return create(data);
            default:
                throw new IllegalArgumentException("radix=" + radix);
        }
    }
    
    /**
     * Creates and returns a random {@link KUID} that has the same
     * prefix as the given {@link KUID}.
     * 
     * NOTE: The bitIndex is counted 0 through n and is inclusive.
     * If you want the first three (3) bits to be the same then
     * pass two (2) as an argument (0 through 2 inclusive is 3).
     */
    public static KUID createWithPrefix(KUID prefix, int bitIndex) {
        // 1) Create a random KUID of the same length
        byte[] dst = new byte[prefix.length()];
        GENERATOR.nextBytes(dst);
        
        // 2) Overwrite the prefix bytes
        ++bitIndex;
        int length = bitIndex/8;
        System.arraycopy(prefix.value, 0, dst, 0, length);
        
        // 3) Overwrite the remaining bits
        int bitsToCopy = bitIndex % 8;
        if (bitsToCopy != 0) {
            // Mask has the low-order (8-bits) bits set
            int mask = (1 << (8-bitsToCopy)) - 1;
            int prefixByte = prefix.value[length];
            int randByte   = dst[length];
            dst[length] = (byte) ((prefixByte & ~mask) | (randByte & mask));
        }
        
        return create(dst);
    }
    
    /**
     * Returns a minimum {@link KUID} of the given length.
     */
    public static KUID min(int length) {
        return new KUID(new byte[length]);
    }
    
    /**
     * Returns a maximum {@link KUID} of the given length.
     */
    public static KUID max(int length) {
        byte[] maxKey = new byte[length];
        Arrays.fill(maxKey, (byte)0xFF);
        return new KUID(maxKey);
    }
    
    private KUID(byte[] key) {
        super(key);
    }
    
    @Override
    public KUID getId() {
        return this;
    }

    /**
     * Returns {@code true} if the given {@link KUID} is compatible with
     * this {@link KUID}.
     */
    public boolean isCompatible(KUID otherId) {
        return otherId != null && length() == otherId.length();
    }
    
    @Override
    public void update(MessageDigest md) {
        md.update(value);
    }
    
    @Override
    public int lengthInBits() {
        return length() * Byte.SIZE;
    }
    
    @Override
    public boolean isBitSet(int bitIndex) {
        int index = (int)(bitIndex / Byte.SIZE);
        int bit = (int)(bitIndex % Byte.SIZE);
        return (value[index] & mask(bit)) != 0;
    }
    
    @Override
    public int bitIndex(KUID otherId) {
        if (!isCompatible(otherId)) {
            throw new IllegalArgumentException("otherKey=" + otherId);            
        }
        
        boolean allNull = true;
        for (int i = 0; i < value.length; i++) {
            byte b1 = value[i];
{'fraction_non_alphanumeric': 0.10732015524866866, 'fraction_numerical': 0.011011824171856666, 'mean_word_length': 2.1884892086330936, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1458279', 'n_tokens_mistral': 3350, 'n_tokens_neox': 3245, 'n_words': 1068}