/* * UIO.java.java * * Created on 03-12-2010 11:24:38 PM * * Copyright 2010 Jonathan Colt * * 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 com.jivesoftware.os.amza.api.filer; import java.io.EOFException; import java.io.IOException; public class UIO { /** * * @param _from * @param _to * @param _bufferSize * @return * @throws Exception */ public static long copy(IReadable _from, IWriteable _to, long _bufferSize) throws Exception { long byteCount = _bufferSize; if (_bufferSize < 1) { byteCount = 1024 * 1024; //1MB } byte[] chunk = new byte[(int) byteCount]; int bytesRead; long size = 0; while ((bytesRead = _from.read(chunk)) > -1) { _to.write(chunk, 0, bytesRead); size += bytesRead; } return size; } /** * * @param _filer * @param bytes * @param fieldName * @throws IOException */ public static void write(IAppendOnly _filer, byte[] bytes, String fieldName) throws IOException { _filer.write(bytes, 0, bytes.length); } /** * * @param _filer * @param v * @param fieldName * @throws IOException */ public static void writeByte(IAppendOnly _filer, byte v, String fieldName) throws IOException { _filer.write(v); } /** * * @param _filer * @param v * @param fieldName * @throws IOException */ public static void writeInt(IAppendOnly _filer, int v, String fieldName, byte[] intBuffer) throws IOException { intBuffer[0] = (byte) (v >>> 24); intBuffer[1] = (byte) (v >>> 16); intBuffer[2] = (byte) (v >>> 8); intBuffer[3] = (byte) (v); _filer.write(intBuffer, 0, 4); } /** * * @param _filer * @param v * @param fieldName * @throws IOException */ public static void writeLong(IAppendOnly _filer, long v, String fieldName, byte[] longBuffer) throws IOException { longBuffer[0] = (byte) (v >>> 56); longBuffer[1] = (byte) (v >>> 48); longBuffer[2] = (byte) (v >>> 40); longBuffer[3] = (byte) (v >>> 32); longBuffer[4] = (byte) (v >>> 24); longBuffer[5] = (byte) (v >>> 16); longBuffer[6] = (byte) (v >>> 8); longBuffer[7] = (byte) (v); _filer.write(longBuffer, 0, 8); } /** * * @param _filer * @param l * @throws IOException */ private static void writeLength(IAppendOnly _filer, int l, byte[] lengthBuffer) throws IOException { writeInt(_filer, l, "length", lengthBuffer); } public static void writeByteArray(IAppendOnly _filer, byte[] array, String fieldName, byte[] lengthBuffer) throws IOException { writeByteArray(_filer, array, 0, array == null ? -1 : array.length, fieldName, lengthBuffer); } /** * * @param _filer * @param array * @param _start * @param _len * @param fieldName * @throws IOException */ public static void writeByteArray(IAppendOnly _filer, byte[] array, int _start, int _len, String fieldName, byte[] lengthBuffer) throws IOException { int len; if (array == null) { len = -1; } else { len = _len; } writeLength(_filer, len, lengthBuffer); if (len < 0) { return; } _filer.write(array, _start, len); } public static void writeLongArray(IAppendOnly _filer, long[] array, String fieldName, byte[] lengthBuffer) throws IOException { int len; if (array == null) { len = -1; } else { len = array.length; } writeLength(_filer, len, lengthBuffer); if (len < 0) { return; } byte[] bytes = new byte[8 * len]; for (int i = 0; i < len; i++) { long v = array[i]; UIO.longBytes(v, bytes, i * 8); } _filer.write(bytes, 0, bytes.length); } public static long[] readLongArray(IReadable _filer, String fieldName, byte[] lengthBuffer) throws IOException { int len = readLength(_filer, lengthBuffer); if (len < 0) { return null; } if (len == 0) { return new long[0]; } long[] array = new long[len]; byte[] bytes = new byte[8 * len]; _filer.read(bytes); int j; for (int i = 0; i < len; i++) { j = i * 8; long v = 0; v |= (bytes[j + 0] & 0xFF); v <<= 8; v |= (bytes[j + 1] & 0xFF); v <<= 8; v |= (bytes[j + 2] & 0xFF); v <<= 8; v |= (bytes[j + 3] & 0xFF); v <<= 8; v |= (bytes[j + 4] & 0xFF); v <<= 8; v |= (bytes[j + 5] & 0xFF); v <<= 8; v |= (bytes[j + 6] & 0xFF); v <<= 8; v |= (bytes[j + 7] & 0xFF); array[i] = v; } return array; } /** * * @param _filer * @return * @throws IOException */ public static int readLength(IReadable _filer, byte[] lengthBuffer) throws IOException { return readInt(_filer, "length", lengthBuffer); } public static int readLength(byte[] array, int _offset) throws IOException { return UIO.bytesInt(array, _offset); } /** * * @param _filer * @param array * @throws IOException */ public static void read(IReadable _filer, byte[] array) throws IOException { readFully(_filer, array, array.length); } /** * * @param _filer * @param fieldName * @return * @throws IOException */ public static byte[] readByteArray(IReadable _filer, String fieldName, byte[] lengthBuffer) throws IOException { int len = readLength(_filer, lengthBuffer); if (len < 0) { return null; } if (len == 0) { return new byte[0]; } byte[] array = new byte[len]; readFully(_filer, array, len); return array; } public static byte[] readByteArray(byte[] bytes, int _offset, String fieldName) throws IOException { int len = readLength(bytes, _offset); if (len < 0) { return null; } if (len == 0) { return new byte[0]; } byte[] array = new byte[len]; readFully(bytes, _offset + 4, array, len); return array; } // Reading /** * * @param _filer * @param fieldName * @return * @throws IOException */ public static boolean readBoolean(IReadable _filer, String fieldName) throws IOException { int v = _filer.read(); if (v < 0) { throw new EOFException(); } return (v != 0); } /** * * @param _filer * @param fieldName * @return * @throws IOException */ public static byte readByte(IReadable _filer, String fieldName) throws IOException { int v = _filer.read(); if (v < 0) { throw new EOFException(); } return (byte) v; } /** * * @param _filer * @param fieldName * @return * @throws IOException */ public static int readInt(IReadable _filer, String fieldName, byte[] intBuffer) throws IOException { readFully(_filer, intBuffer, 4); int v = 0; v |= (intBuffer[0] & 0xFF); v <<= 8; v |= (intBuffer[1] & 0xFF); v <<= 8; v |= (intBuffer[2] & 0xFF); v <<= 8; v |= (intBuffer[3] & 0xFF); return v; } /** * * @param _filer * @param fieldName * @return * @throws IOException */ public static long readLong(IReadable _filer, String fieldName, byte[] longBuffer) throws IOException { readFully(_filer, longBuffer, 8); long v = 0; v |= (longBuffer[0] & 0xFF); v <<= 8; v |= (longBuffer[1] & 0xFF); v <<= 8; v |= (longBuffer[2] & 0xFF); v <<= 8; v |= (longBuffer[3] & 0xFF); v <<= 8; v |= (longBuffer[4] & 0xFF); v <<= 8; v |= (longBuffer[5] & 0xFF); v <<= 8; v |= (longBuffer[6] & 0xFF); v <<= 8; v |= (longBuffer[7] & 0xFF); return v; } public static boolean bytesBoolean(byte[] bytes, int _offset) { if (bytes == null) { return false; } return bytes[_offset] != 0; } /** * * @param v * @return */ public static byte[] intBytes(int v) { return intBytes(v, new byte[4], 0); } /** * * @param v * @param _bytes * @param _offset * @return */ public static byte[] intBytes(int v, byte[] _bytes, int _offset) { _bytes[_offset + 0] = (byte) (v >>> 24); _bytes[_offset + 1] = (byte) (v >>> 16); _bytes[_offset + 2] = (byte) (v >>> 8); _bytes[_offset + 3] = (byte) v; return _bytes; } /** * * @param _bytes * @return */ public static int bytesInt(byte[] _bytes) { return bytesInt(_bytes, 0); } /** * * @param v * @param _bytes * @param _offset * @return */ public static byte[] shortBytes(short v, byte[] _bytes, int _offset) { _bytes[_offset + 0] = (byte) (v >>> 8); _bytes[_offset + 1] = (byte) v; return _bytes; } /** * * @param _bytes * @return */ public static short bytesShort(byte[] _bytes) { return bytesShort(_bytes, 0); } public static byte[] unsignedShortBytes(int v, byte[] bytes, int offset) { bytes[offset + 0] = (byte) (v >>> 8); bytes[offset + 1] = (byte) v; return bytes; } public static int bytesUnsignedShort(byte[] bytes, int offset) { int v = 0; v |= (bytes[offset + 0] & 0xFF); v <<= 8; v |= (bytes[offset + 1] & 0xFF); return v; } /** * * @param _bytes * @return */ public static int[] bytesInts(byte[] _bytes) { if (_bytes == null || _bytes.length == 0) { return null; } int intsCount = _bytes.length / 4; int[] ints = new int[intsCount]; for (int i = 0; i < intsCount; i++) { ints[i] = bytesInt(_bytes, i * 4); } return ints; } /** * * @param bytes * @param _offset * @return */ public static int bytesInt(byte[] bytes, int _offset) { int v = 0; v |= (bytes[_offset + 0] & 0xFF); v <<= 8; v |= (bytes[_offset + 1] & 0xFF); v <<= 8; v |= (bytes[_offset + 2] & 0xFF); v <<= 8; v |= (bytes[_offset + 3] & 0xFF); return v; } /** * * @param bytes * @param _offset * @return */ public static short bytesShort(byte[] bytes, int _offset) { short v = 0; v |= (bytes[_offset + 0] & 0xFF); v <<= 8; v |= (bytes[_offset + 1] & 0xFF); return v; } /** * * @param _longs * @return */ public static byte[] longsBytes(long[] _longs) { int len = _longs.length; byte[] bytes = new byte[len * 8]; for (int i = 0; i < len; i++) { longBytes(_longs[i], bytes, i * 8); } return bytes; } /** * * @param _v * @return */ public static byte[] longBytes(long _v) { return longBytes(_v, new byte[8], 0); } /** * * @param v * @param _bytes * @param _offset * @return */ public static byte[] longBytes(long v, byte[] _bytes, int _offset) { _bytes[_offset + 0] = (byte) (v >>> 56); _bytes[_offset + 1] = (byte) (v >>> 48); _bytes[_offset + 2] = (byte) (v >>> 40); _bytes[_offset + 3] = (byte) (v >>> 32); _bytes[_offset + 4] = (byte) (v >>> 24); _bytes[_offset + 5] = (byte) (v >>> 16); _bytes[_offset + 6] = (byte) (v >>> 8); _bytes[_offset + 7] = (byte) v; return _bytes; } /** * * @param _bytes * @return */ public static long bytesLong(byte[] _bytes) { return bytesLong(_bytes, 0); } /** * * @param _bytes * @return */ public static long[] bytesLongs(byte[] _bytes) { if (_bytes == null || _bytes.length == 0) { return null; } int longsCount = _bytes.length / 8; long[] longs = new long[longsCount]; for (int i = 0; i < longsCount; i++) { longs[i] = bytesLong(_bytes, i * 8); } return longs; } /** * * @param bytes * @param _offset * @return */ public static long bytesLong(byte[] bytes, int _offset) { if (bytes == null) { return 0; } long v = 0; v |= (bytes[_offset + 0] & 0xFF); v <<= 8; v |= (bytes[_offset + 1] & 0xFF); v <<= 8; v |= (bytes[_offset + 2] & 0xFF); v <<= 8; v |= (bytes[_offset + 3] & 0xFF); v <<= 8; v |= (bytes[_offset + 4] & 0xFF); v <<= 8; v |= (bytes[_offset + 5] & 0xFF); v <<= 8; v |= (bytes[_offset + 6] & 0xFF); v <<= 8; v |= (bytes[_offset + 7] & 0xFF); return v; } /** * * @param length * @param _minPower * @return */ public static int chunkPower(long length, int _minPower) { if (length == 0) { return 0; } int numberOfTrailingZeros = Long.numberOfLeadingZeros(length - 1); return Math.max(_minPower, 64 - numberOfTrailingZeros); } /** * * @param _chunkPower * @return */ public static long chunkLength(int _chunkPower) { return 1L << _chunkPower; } public static int writeInt(int v, byte[] destination, int offset) { destination[offset + 0] = (byte) (v >>> 24); destination[offset + 1] = (byte) (v >>> 16); destination[offset + 2] = (byte) (v >>> 8); destination[offset + 3] = (byte) v; return 4; } public static int writeBytes(byte[] value, byte[] destination, int offset) { if (value != null) { System.arraycopy(value, 0, destination, offset, value.length); return value.length; } return 0; } public static void readBytes(byte[] source, int offset, byte[] value) { System.arraycopy(source, offset, value, 0, value.length); } private static void readFully(IReadable readable, byte[] into, int length) throws IOException { int read = readable.read(into, 0, length); if (read != length) { throw new IOException("Failed to fully. Only had " + read + " needed " + length); } } private static void readFully(byte[] from, int offset, byte[] into, int length) throws IOException { System.arraycopy(from, offset, into, 0, length); } }