* * 1 Byte - 00xxxxxx Represents the value <= 63 (0x3f) 2 Byte - 01xxxxxx * xxxxxxxx Represents the value > 63 && <= 16383 (0x3fff) 4 byte - 1xxxxxxx * xxxxxxxx xxxxxxxx xxxxxxxx Represents the value > 16383 && <= MAX_INT * ** * * @exception IOException * value is negative or an exception was thrown by a method on * out. */ public static final int writeInt(DataOutput out, int value) throws IOException { if (value < 0) throw new IOException(); if (value <= 0x3f) { out.writeByte(value); return 1; } if (value <= 0x3fff) { out.writeByte(0x40 | (value >>> 8)); out.writeByte(value & 0xff); return 2; } out.writeByte(((value >>> 24) | 0x80) & 0xff); out.writeByte((value >>> 16) & 0xff); out.writeByte((value >>> 8) & 0xff); out.writeByte((value) & 0xff); return 4; } /** * Write a compressed integer directly to an OutputStream. * * @exception IOException * an exception was thrown by a method on in. */ public static final int writeInt(OutputStream out, int value) throws IOException { if (value < 0) throw new IOException(); if (value <= 0x3f) { out.write(value); return 1; } if (value <= 0x3fff) { out.write(0x40 | (value >>> 8)); out.write(value & 0xff); return 2; } out.write(((value >>> 24) | 0x80) & 0xff); out.write((value >>> 16) & 0xff); out.write((value >>> 8) & 0xff); out.write((value) & 0xff); return 4; } /** * Read an integer previously written by writeInt(). * * @exception IOException * an exception was thrown by a method on in. */ public static final int readInt(DataInput in) throws IOException { int value = in.readUnsignedByte(); if ((value & ~0x3f) == 0) { // length is stored in this byte, we also know that the 0x80 bit // was not set, so no need to mask off the sign extension from // the byte to int conversion. // account for 1 byte stored length of field + 1 for all returns return (value); } else if ((value & 0x80) == 0) { // length is stored in 2 bytes. only use low 6 bits from 1st byte. // top 8 bits of 2 byte length is stored in this byte, we also // know that the 0x80 bit was not set, so no need to mask off the // sign extension from the 1st byte to int conversion. Need to // mask the byte in data[offset + 1] to account for possible sign // extension. return (((value & 0x3f) << 8) | in.readUnsignedByte()); } else { // top 8 bits of 4 byte length is stored in this byte, we also // know that the 0x80 bit was set, so need to mask off the // sign extension from the 1st byte to int conversion. Need to // mask the bytes from the next 3 bytes data[offset + 1,2,3] to // account for possible sign extension. // return (((value & 0x7f) << 24) | (in.readUnsignedByte() << 16) | (in.readUnsignedByte() << 8) | (in .readUnsignedByte())); } } /** * Read an integer previously written by writeInt(). * * @exception IOException * an exception was thrown by a method on in. */ public static final int readInt(InputStream in) throws IOException { int value = InputStreamUtil.readUnsignedByte(in); if ((value & ~0x3f) == 0) { return (value); } else if ((value & 0x80) == 0) { return (((value & 0x3f) << 8) | InputStreamUtil.readUnsignedByte(in)); } else { return (((value & 0x7f) << 24) | (InputStreamUtil.readUnsignedByte(in) << 16) | (InputStreamUtil.readUnsignedByte(in) << 8) | (InputStreamUtil.readUnsignedByte(in))); } } public static final int readInt(byte[] data, int offset) { int value = data[offset++]; if ((value & ~0x3f) == 0) { // length is stored in this byte, we also know that the 0x80 bit // was not set, so no need to mask off the sign extension from // the byte to int conversion. return (value); } else if ((value & 0x80) == 0) { // length is stored in 2 bytes. only use low 6 bits from 1st byte. // top 8 bits of 2 byte length is stored in this byte, we also // know that the 0x80 bit was not set, so no need to mask off the // sign extension from the 1st byte to int conversion. Need to // mask the byte in data[offset + 1] to account for possible sign // extension. return (((value & 0x3f) << 8) | (data[offset] & 0xff)); } else { // top 8 bits of 4 byte length is stored in this byte, we also // know that the 0x80 bit was set, so need to mask off the // sign extension from the 1st byte to int conversion. Need to // mask the bytes from the next 3 bytes data[offset + 1,2,3] to // account for possible sign extension. // return (((value & 0x7f) << 24) | ((data[offset++] & 0xff) << 16) | ((data[offset++] & 0xff) << 8) | ((data[offset] & 0xff))); } } /** * Skip an integer previously written by writeInt(). * * @exception IOException * an exception was thrown by a method on in. */ /** * Return the number of bytes that would be written by a writeInt call */ public static final int sizeInt(int value) { if (value <= 0x3f) { return 1; } if (value <= 0x3fff) { return 2; } return 4; } /** * Write a compressed long only supporting signed values. * * Formats are (with x representing value bits): * *
* * 2 byte - 00xxxxxx xxxxxxxx Represents the value <= 16383 (0x3fff) 4 byte - * 01xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx Represents the value > 16383 && <= * 0x3fffffff 8 byte - 1xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx * xxxxxxxx xxxxxxxx Represents the value > 0x3fffffff && <= MAX_LONG * ** * * @exception IOException * value is negative or an exception was thrown by a method on * out. */ public static final int writeLong(DataOutput out, long value) throws IOException { if (value < 0) throw new IOException(); if (value <= 0x3fff) { out.writeByte((int) ((value >>> 8) & 0xff)); out.writeByte((int) ((value) & 0xff)); return 2; } if (value <= 0x3fffffff) { out.writeByte((int) (((value >>> 24) | 0x40) & 0xff)); out.writeByte((int) ((value >>> 16) & 0xff)); out.writeByte((int) ((value >>> 8) & 0xff)); out.writeByte((int) ((value) & 0xff)); return 4; } out.writeByte((int) (((value >>> 56) | 0x80) & 0xff)); out.writeByte((int) ((value >>> 48) & 0xff)); out.writeByte((int) ((value >>> 40) & 0xff)); out.writeByte((int) ((value >>> 32) & 0xff)); out.writeByte((int) ((value >>> 24) & 0xff)); out.writeByte((int) ((value >>> 16) & 0xff)); out.writeByte((int) ((value >>> 8) & 0xff)); out.writeByte((int) ((value) & 0xff)); return 8; } /** * Write a compressed integer only supporting signed values. * * @exception IOException * value is negative or an exception was thrown by a method on * out. */ public static final int writeLong(OutputStream out, long value) throws IOException { if (value < 0) throw new IOException(); if (value <= 0x3fff) { out.write((int) ((value >>> 8) & 0xff)); out.write((int) ((value) & 0xff)); return 2; } if (value <= 0x3fffffff) { out.write((int) (((value >>> 24) | 0x40) & 0xff)); out.write((int) ((value >>> 16) & 0xff)); out.write((int) ((value >>> 8) & 0xff)); out.write((int) ((value) & 0xff)); return 4; } out.write((int) (((value >>> 56) | 0x80) & 0xff)); out.write((int) ((value >>> 48) & 0xff)); out.write((int) ((value >>> 40) & 0xff)); out.write((int) ((value >>> 32) & 0xff)); out.write((int) ((value >>> 24) & 0xff)); out.write((int) ((value >>> 16) & 0xff)); out.write((int) ((value >>> 8) & 0xff)); out.write((int) ((value) & 0xff)); return 8; } /** * Read a long previously written by writeLong(). * * @exception IOException * an exception was thrown by a method on in. */ public static final long readLong(DataInput in) throws IOException { int int_value = in.readUnsignedByte(); if ((int_value & ~0x3f) == 0) { // test for small case first - assuming this is usual case. // this is stored in 2 bytes. return ((int_value << 8) | in.readUnsignedByte()); } else if ((int_value & 0x80) == 0) { // value is stored in 4 bytes. only use low 6 bits from 1st byte. return (((int_value & 0x3f) << 24) | (in.readUnsignedByte() << 16) | (in.readUnsignedByte() << 8) | (in.readUnsignedByte())); } else { // value is stored in 8 bytes. only use low 7 bits from 1st byte. return ((((long) (int_value & 0x7f)) << 56) | (((long) in.readUnsignedByte()) << 48) | (((long) in.readUnsignedByte()) << 40) | (((long) in.readUnsignedByte()) << 32) | (((long) in.readUnsignedByte()) << 24) | (((long) in.readUnsignedByte()) << 16) | (((long) in.readUnsignedByte()) << 8) | (((long) in.readUnsignedByte()))); } } /** * Read a long previously written by writeLong(). * * @exception IOException * an exception was thrown by a method on in. */ public static final long readLong(InputStream in) throws IOException { int int_value = InputStreamUtil.readUnsignedByte(in); if ((int_value & ~0x3f) == 0) { // test for small case first - assuming this is usual case. // this is stored in 2 bytes. return ((int_value << 8) | InputStreamUtil.readUnsignedByte(in)); } else if ((int_value & 0x80) == 0) { // value is stored in 4 bytes. only use low 6 bits from 1st byte. return (((int_value & 0x3f) << 24) | (InputStreamUtil.readUnsignedByte(in) << 16) | (InputStreamUtil.readUnsignedByte(in) << 8) | (InputStreamUtil.readUnsignedByte(in))); } else { // value is stored in 8 bytes. only use low 7 bits from 1st byte. long value = int_value; return ((((long) (value & 0x7f)) << 56) | (((long) InputStreamUtil.readUnsignedByte(in)) << 48) | (((long) InputStreamUtil.readUnsignedByte(in)) << 40) | (((long) InputStreamUtil.readUnsignedByte(in)) << 32) | (((long) InputStreamUtil.readUnsignedByte(in)) << 24) | (((long) InputStreamUtil.readUnsignedByte(in)) << 16) | (((long) InputStreamUtil.readUnsignedByte(in)) << 8) | (((long) InputStreamUtil .readUnsignedByte(in)))); } } public static final long readLong(byte[] data, int offset) { int int_value = data[offset++]; if ((int_value & ~0x3f) == 0) { // test for small case first - assuming this is usual case. // this is stored in 2 bytes. return ((int_value << 8) | (data[offset] & 0xff)); } else if ((int_value & 0x80) == 0) { // value is stored in 4 bytes. only use low 6 bits from 1st byte. return (((int_value & 0x3f) << 24) | ((data[offset++] & 0xff) << 16) | ((data[offset++] & 0xff) << 8) | ((data[offset] & 0xff))); } else { // value is stored in 8 bytes. only use low 6 bits from 1st byte. return ((((long) (int_value & 0x7f)) << 56) | (((long) (data[offset++] & 0xff)) << 48) | (((long) (data[offset++] & 0xff)) << 40) | (((long) (data[offset++] & 0xff)) << 32) | (((long) (data[offset++] & 0xff)) << 24) | (((long) (data[offset++] & 0xff)) << 16) | (((long) (data[offset++] & 0xff)) << 8) | (((long) (data[offset] & 0xff)))); } } public static final int sizeLong(long value) { if (value <= 0x3fff) { return 2; } if (value <= 0x3fffffff) { return 4; } return 8; } } /* * * Derby - Class org.apache.derby.iapi.services.io.InputStreamUtil * * 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. * */ /** * Utility methods for InputStream that are stand-ins for a small subset of * DataInput methods. This avoids pushing a DataInputStream just to get this * functionality. */ final class InputStreamUtil { private static final int SKIP_FRAGMENT_SIZE = Integer.MAX_VALUE; /** * Read an unsigned byte from an InputStream, throwing an EOFException if the * end of the input is reached. * * @exception IOException * if an I/O error occurs. * @exception EOFException * if the end of the stream is reached * * @see DataInput#readUnsignedByte * */ public static int readUnsignedByte(InputStream in) throws IOException { int b = in.read(); if (b < 0) throw new EOFException(); return b; } /** * Read a number of bytes into an array. * * @exception IOException * if an I/O error occurs. * @exception EOFException * if the end of the stream is reached * * @see DataInput#readFully * */ public static void readFully(InputStream in, byte b[], int offset, int len) throws IOException { do { int bytesRead = in.read(b, offset, len); if (bytesRead < 0) throw new EOFException(); len -= bytesRead; offset += bytesRead; } while (len != 0); } /** * Read a number of bytes into an array. Keep reading in a loop until len * bytes are read or EOF is reached or an exception is thrown. Return the * number of bytes read. (InputStream.read(byte[],int,int) does not guarantee * to read len bytes even if it can do so without reaching EOF or raising an * exception.) * * @exception IOException * if an I/O error occurs. */ public static int readLoop(InputStream in, byte b[], int offset, int len) throws IOException { int firstOffset = offset; do { int bytesRead = in.read(b, offset, len); if (bytesRead <= 0) break; len -= bytesRead; offset += bytesRead; } while (len != 0); return offset - firstOffset; } /** * Skips until EOF, returns number of bytes skipped. * * @param is * InputStream to be skipped. * @return number of bytes skipped in fact. * @throws IOException * if IOException occurs. It doesn't contain EOFException. * @throws NullPointerException * if the param 'is' equals null. */ public static long skipUntilEOF(InputStream is) throws IOException { if (is == null) throw new NullPointerException(); long bytes = 0; while (true) { long r = skipPersistent(is, SKIP_FRAGMENT_SIZE); bytes += r; if (r < SKIP_FRAGMENT_SIZE) return bytes; } } /** * Skips requested number of bytes, throws EOFException if there is too few * bytes in the stream. * * @param is * InputStream to be skipped. * @param skippedBytes * number of bytes to skip. if skippedBytes <= zero, do nothing. * @throws EOFException * if EOF meets before requested number of bytes are skipped. * @throws IOException * if IOException occurs. It doesn't contain EOFException. * @throws NullPointerException * if the param 'is' equals null. */ public static void skipFully(InputStream is, long skippedBytes) throws IOException { if (is == null) throw new NullPointerException(); if (skippedBytes <= 0) return; long bytes = skipPersistent(is, skippedBytes); if (bytes < skippedBytes) throw new EOFException(); } /** * Tries harder to skip the requested number of bytes. *
* Note that even if the method fails to skip the requested number of bytes, * it will not throw an exception. If this happens, the caller can be sure * that end-of-stream has been reached. * * @param in * byte stream * @param bytesToSkip * the number of bytes to skip * @return The number of bytes skipped. * @throws IOException * if reading from the stream fails */ public static final long skipPersistent(InputStream in, long bytesToSkip) throws IOException { long skipped = 0; while (skipped < bytesToSkip) { long skippedNow = in.skip(bytesToSkip - skipped); if (skippedNow == 0) { if (in.read() == -1) { // EOF, return what we have and leave it up to caller to // decide what to do about it. break; } else { skippedNow = 1; // Added to count below. } } skipped += skippedNow; } return skipped; } }