io.blobkeeper.common.util.Utils.java Source code

Java tutorial

Introduction

Here is the source code for io.blobkeeper.common.util.Utils.java

Source

package io.blobkeeper.common.util;

/*
 * Copyright (C) 2015 by Denis M. Gabaydulin
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.
 */

import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Range;
import org.jetbrains.annotations.NotNull;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.SortedMap;
import java.util.function.BinaryOperator;

public class Utils {
    private Utils() {
    }

    /**
     * @return The bitwise XOR of the inputs. The output will be the same length as the
     * longer input, but if either input is null, the output will be null.
     */
    public static byte[] xor(byte[] left, byte[] right) {
        if (left == null || right == null) {
            return null;
        }

        if (left.length > right.length) {
            byte[] swap = left;
            left = right;
            right = swap;
        }

        // left.length is now <= right.length
        byte[] out = Arrays.copyOf(right, right.length);
        for (int i = 0; i < left.length; i++) {
            out[i] = (byte) ((left[i] & 0xFF) ^ (right[i] & 0xFF));
        }
        return out;
    }

    public static long midPoint(long left, long right) {
        // using BigInteger to avoid long overflow in intermediate operations
        BigInteger l = BigInteger.valueOf(left);
        BigInteger r = BigInteger.valueOf(right);
        BigInteger midPoint;

        if (l.compareTo(r) < 0) {
            BigInteger sum = l.add(r);
            midPoint = sum.shiftRight(1);
        } else { // wrapping case
            BigInteger max = BigInteger.valueOf(Long.MAX_VALUE);
            BigInteger min = BigInteger.valueOf(Long.MIN_VALUE);
            // length of range we're bisecting is (R - min) + (max - L)
            // so we add that to L giving
            // L + ((R - min) + (max - L) / 2) = (L + R + max - min) / 2
            midPoint = (max.subtract(min).add(l).add(r)).shiftRight(1);
            if (midPoint.compareTo(max) > 0)
                midPoint = min.add(midPoint.subtract(max));
        }

        return midPoint.longValue();
    }

    public static <T> BinaryOperator<T> throwingMerger() {
        return (u, v) -> {
            throw new IllegalStateException(String.format("Duplicate key %s", u));
        };
    }

    public static MerkleTree createEmptyTree(@NotNull Range<Long> range, int depth) {
        MerkleTree tree = new MerkleTree(range, depth);
        MerkleTree.fillTree(tree, ImmutableSortedMap.of());
        tree.calculate();
        return tree;
    }

    public static MerkleTree createTree(@NotNull Range<Long> range, int depth,
            @NotNull SortedMap<Long, Block> blocks) {
        MerkleTree tree = new MerkleTree(range, depth);
        MerkleTree.fillTree(tree, blocks);
        tree.calculate();
        return tree;
    }
}