/*
* Copyright 2009-2016 Tilmann Zaeschke. All rights reserved.
*
* This file is part of ZooDB.
*
* ZooDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* ZooDB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ZooDB. If not, see <http://www.gnu.org/licenses/>.
*
* See the README and COPYING files for further information.
*/
package org.zoodb.internal.server.index;
import org.zoodb.api.impl.ZooPC;
public class BitTools {
/** Value to recognize 'null'in indices. Using MIN_VALUE so that NULL is the lowest value
* when sorted. */
public static final long NULL = Long.MIN_VALUE;
public static final long EMPTY_STRING = 0L;
public static final long getMinPosInPage(long pos) {
return pos & 0xFFFFFFFF00000000L;
}
public static final long getMaxPosInPage(long pos) {
return pos | 0x00000000FFFFFFFFL;
}
public static final int getPage(long pos) {
return (int) (pos >> 32);
}
public static final int getOffs(long pos) {
return (int)(pos & 0x00000000FFFFFFFFL);
}
public static final long getPos(int pageId, int offs) {
return (((long)pageId) << 32) + offs;
}
/**
* @param value
* @return long representation.
*/
public static long toSortableLong(double value) {
//To create a sortable long, we convert the double to a long using the IEEE-754 standard,
//which stores floats in the form <sign><exponent-127><mantissa> .
//This result is properly ordered longs for all positive doubles. Negative values have
//inverse ordering. For negative doubles, we therefore simply invert them to make them
//sortable, however the sign must be inverted again to stay negative.
long r = Double.doubleToRawLongBits(value);
return (r >= 0) ? r : r ^ 0x7FFFFFFFFFFFFFFFL;
}
public static long toSortableLong(float value) {
//see toSortableLong(double)
int r = Float.floatToRawIntBits(value);
return (r >= 0) ? r : r ^ 0x7FFFFFFF;
}
public static double toDouble(long value) {
return Double.longBitsToDouble(value >= 0.0 ? value : value ^ 0x7FFFFFFFFFFFFFFFL);
}
public static float toFloat(long value) {
int iVal = (int) value;
return Float.intBitsToFloat(iVal >= 0.0 ? iVal : iVal ^ 0x7FFFFFFF);
}
public static long toSortableLong(String s) {
if (s == null) {
return NULL;
}
if (s.length() == 0) {
return EMPTY_STRING;
}
// store magic number: 6 chars + (hash >> 16)
long n = 0;
int i = 0;
for ( ; i < 6 && i < s.length(); i++ ) {
n |= (byte) s.charAt(i);
n = n << 8;
}
//Fill with empty spaces if string is too short
for ( ; i < 6; i++) {
n = n << 8;
}
n = n << 8;
//add hashcode
n |= (0xFFFF & s.hashCode());
return n;
}
public static long toSortableLong(ZooPC pc) {
if (pc == null) {
return NULL;
}
return pc.jdoZooGetOid();
}
/**
* @param prefix
* @return the minimum index-key for strings with the given prefix
*/
public static long toSortableLongPrefixMinHash(String prefix) {
if (prefix != null && prefix.length() == 0) {
return Long.MIN_VALUE;
}
long key = toSortableLong(prefix);
return key & ((prefix.length() < 6)
? ~(0xFFFFFFFFFFFFFFFFL >>> (prefix.length()*8))
: 0xFFFFFFFFFFFF0000L);
}
/**
* @param prefix
* @return the maximum index-key for strings with the given prefix
*/
public static long toSortableLongPrefixMaxHash(String prefix) {
if (prefix != null && prefix.length() == 0) {
return Long.MAX_VALUE;
}
long key = toSortableLong(prefix);
return key | ((prefix.length() < 6)
? 0xFFFFFFFFFFFFFFFFL >>> (prefix.length()*8)
: 0x000000000000FFFFL);
}
}