/* * Copyright 2011 b1.org * * 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.b1.pack.standard.common; import com.google.common.base.Preconditions; import java.io.*; public class Numbers { public static final int MAX_LONG_SIZE = getSerializedSize(Long.MIN_VALUE); public static final int MAX_INT_SIZE = getSerializedSize((long) Integer.MIN_VALUE); public static byte[] serializeLong(Long value) { try { ByteArrayOutputStream stream = new ByteArrayOutputStream(); writeLong(value, stream); return stream.toByteArray(); } catch (IOException e) { throw new RuntimeException(e); } } public static byte[] serializeLong(Long value, int size) { try { ByteArrayOutputStream stream = new ByteArrayOutputStream(); writeLong(value, stream); int minSize = stream.size(); if (minSize == size) { return stream.toByteArray(); } Preconditions.checkArgument(minSize < size); while (stream.size() < size - 1) { stream.write(0x80); } stream.write(0); byte[] result = stream.toByteArray(); result[minSize - 1] |= 0x80; return result; } catch (IOException e) { throw new RuntimeException(e); } } public static int getSerializedSize(long value) { return serializeLong(value).length; } public static void writeLong(Long value, OutputStream stream) throws IOException { if (value == null) { stream.write(1); } else { writeLong(value.longValue(), stream); } } public static void writeLong(long value, OutputStream stream) throws IOException { int sign = 0; if (value < 0) { sign = 1; value = -value; } int b = (int) ((value & 0x3F) << 1) | sign; value >>>= 6; while (value != 0) { stream.write(b | 0x80); b = (int) (value & 0x7F); value >>>= 7; } stream.write(b); } public static Long readLong(InputStream stream) throws IOException { int b = read(stream); int sign = b & 1; long value = (b >> 1) & 0x3F; for (int i = 6; (b & 0x80) != 0; i += 7) { b = read(stream); long bits = b & 0x7FL; if (i >= 62 && bits != 0 && (i > 62 || (bits == 2 ? value != 0 : bits != 1))) { throw new IllegalArgumentException("Value too long"); } value |= bits << i; } return sign == 0 ? Long.valueOf(value) : value == 0 ? null : -value; } private static int read(InputStream stream) throws IOException { int result = stream.read(); if (result == -1) { throw new EOFException(); } return result; } }