KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > util > PackedInteger


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2000,2006 Oracle. All rights reserved.
5  *
6  * $Id: PackedInteger.java,v 1.4 2006/10/30 21:14:35 bostic Exp $
7  */

8
9 package com.sleepycat.util;
10
11 /**
12  * Static methods for reading and writing packed integers.
13  *
14  * <p>Note that packed integers are not sorted naturally for a byte-by-byte
15  * comparison because they have a preceding length and are little endian;
16  * therefore, they are typically not used for keys.</p>
17  *
18  * <p>Values in the inclusive range [-119,119] are stored in a single byte.
19  * For values outside that range, the first byte stores the sign and the number
20  * of additional bytes. The additional bytes store (abs(value) - 119) as an
21  * unsigned little endian integer.</p>
22  *
23  * <p>To read and write packed integer values, call {@link #readInt} and {@link
24  * #writeInt}. To get the length of a packed integer without reading it, call
25  * {@link #getReadIntLength}. To get the length of an unpacked integer without
26  * writing it, call {@link #getWriteIntLength}.</p>
27  *
28  * <p>Note that the packed integer format is designed to accomodate long
29  * integers using up to 9 bytes of storage. Currently only int values are
30  * implemented, but the same format may be used in future for long values.</p>
31  */

32 public class PackedInteger {
33
34     /**
35      * The maximum number of bytes needed to store an int value (5). The fifth
36      * byte is only needed for values greater than (Integer.MAX_VALUE - 119) or
37      * less than (Integer.MIN_VALUE + 119).
38      */

39     public static final int MAX_LENGTH = 5;
40
41     /**
42      * Reads a packed integer at the given buffer offset and returns it.
43      *
44      * @param buf the buffer to read from.
45      *
46      * @param off the offset in the buffer at which to start reading.
47      *
48      * @return the integer that was read.
49      */

50     public static int readInt(byte[] buf, int off) {
51
52         boolean negative;
53         int byteLen;
54
55         int b1 = buf[off++];
56         if (b1 < -119) {
57             negative = true;
58             byteLen = -b1 - 119;
59         } else if (b1 > 119) {
60             negative = false;
61             byteLen = b1 - 119;
62         } else {
63             return b1;
64         }
65
66         int value = buf[off++] & 0xFF;
67         if (byteLen > 1) {
68             value |= (buf[off++] & 0xFF) << 8;
69             if (byteLen > 2) {
70                 value |= (buf[off++] & 0xFF) << 16;
71                 if (byteLen > 3) {
72                     value |= (buf[off++] & 0xFF) << 24;
73                 }
74             }
75         }
76
77         return negative ? (-value - 119) : (value + 119);
78     }
79
80     /**
81      * Returns the number of bytes that would be read by {@link #readInt}.
82      *
83      * @param buf the buffer to read from.
84      *
85      * @param off the offset in the buffer at which to start reading.
86      *
87      * @return the number of bytes that would be read.
88      */

89     public static int getReadIntLength(byte[] buf, int off) {
90
91         int b1 = buf[off];
92         if (b1 < -119) {
93             return -b1 - 119 + 1;
94         } else if (b1 > 119) {
95             return b1 - 119 + 1;
96         } else {
97             return 1;
98         }
99     }
100
101     /**
102      * Writes a packed integer starting at the given buffer offset and returns
103      * the next offset to be written.
104      *
105      * @param buf the buffer to write to.
106      *
107      * @param offset the offset in the buffer at which to start writing.
108      *
109      * @param value the integer to be written.
110      *
111      * @return the offset past the bytes written.
112      */

113     public static int writeInt(byte[] buf, int offset, int value) {
114
115         int byte1Off = offset;
116         boolean negative;
117
118         if (value < -119) {
119             negative = true;
120             value = -value - 119;
121         } else if (value > 119) {
122             negative = false;
123             value = value - 119;
124         } else {
125             buf[offset++] = (byte) value;
126             return offset;
127         }
128         offset++;
129
130         buf[offset++] = (byte) value;
131         if ((value & 0xFFFFFF00) == 0) {
132             buf[byte1Off] = negative ? (byte) -120 : (byte) 120;
133             return offset;
134         }
135
136         buf[offset++] = (byte) (value >>> 8);
137         if ((value & 0xFFFF0000) == 0) {
138             buf[byte1Off] = negative ? (byte) -121 : (byte) 121;
139             return offset;
140         }
141
142         buf[offset++] = (byte) (value >>> 16);
143         if ((value & 0xFF000000) == 0) {
144             buf[byte1Off] = negative ? (byte) -122 : (byte) 122;
145             return offset;
146         }
147
148         buf[offset++] = (byte) (value >>> 24);
149         buf[byte1Off] = negative ? (byte) -123 : (byte) 123;
150         return offset;
151     }
152
153     /**
154      * Returns the number of bytes that would be written by {@link #writeInt}.
155      *
156      * @param value the integer to be written.
157      *
158      * @return the number of bytes that would be used to write the given
159      * integer.
160      */

161     public static int getWriteIntLength(int value) {
162
163         if (value < -119) {
164             value = -value - 119;
165         } else if (value > 119) {
166             value = value - 119;
167         } else {
168             return 1;
169         }
170
171         if ((value & 0xFFFFFF00) == 0) {
172             return 2;
173         }
174         if ((value & 0xFFFF0000) == 0) {
175             return 3;
176         }
177         if ((value & 0xFF000000) == 0) {
178             return 4;
179         }
180         return 5;
181     }
182 }
183
Popular Tags