1 /*
2 * Copyright (C) 2008, 2015 Shawn O. Pearce <spearce@spearce.org>
3 * and other copyright owners as documented in the project's IP log.
4 *
5 * This program and the accompanying materials are made available
6 * under the terms of the Eclipse Distribution License v1.0 which
7 * accompanies this distribution, is reproduced below, and is
8 * available at http://www.eclipse.org/org/documents/edl-v10.php
9 *
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
14 * conditions are met:
15 *
16 * - Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials provided
22 * with the distribution.
23 *
24 * - Neither the name of the Eclipse Foundation, Inc. nor the
25 * names of its contributors may be used to endorse or promote
26 * products derived from this software without specific prior
27 * written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 */
43
44 package org.eclipse.jgit.util;
45
46 /**
47 * Conversion utilities for network byte order handling.
48 */
49 public final class NB {
50 /**
51 * Compare a 32 bit unsigned integer stored in a 32 bit signed integer.
52 * <p>
53 * This function performs an unsigned compare operation, even though Java
54 * does not natively support unsigned integer values. Negative numbers are
55 * treated as larger than positive ones.
56 *
57 * @param a
58 * the first value to compare.
59 * @param b
60 * the second value to compare.
61 * @return < 0 if a < b; 0 if a == b; > 0 if a > b.
62 */
63 public static int compareUInt32(final int a, final int b) {
64 final int cmp = (a >>> 1) - (b >>> 1);
65 if (cmp != 0)
66 return cmp;
67 return (a & 1) - (b & 1);
68 }
69
70 /**
71 * Compare a 64 bit unsigned integer stored in a 64 bit signed integer.
72 * <p>
73 * This function performs an unsigned compare operation, even though Java
74 * does not natively support unsigned integer values. Negative numbers are
75 * treated as larger than positive ones.
76 *
77 * @param a
78 * the first value to compare.
79 * @param b
80 * the second value to compare.
81 * @return < 0 if a < b; 0 if a == b; > 0 if a > b.
82 * @since 4.3
83 */
84 public static int compareUInt64(final long a, final long b) {
85 long cmp = (a >>> 1) - (b >>> 1);
86 if (cmp > 0) {
87 return 1;
88 } else if (cmp < 0) {
89 return -1;
90 }
91 cmp = ((a & 1) - (b & 1));
92 if (cmp > 0) {
93 return 1;
94 } else if (cmp < 0) {
95 return -1;
96 } else {
97 return 0;
98 }
99 }
100
101 /**
102 * Convert sequence of 2 bytes (network byte order) into unsigned value.
103 *
104 * @param intbuf
105 * buffer to acquire the 2 bytes of data from.
106 * @param offset
107 * position within the buffer to begin reading from. This
108 * position and the next byte after it (for a total of 2 bytes)
109 * will be read.
110 * @return unsigned integer value that matches the 16 bits read.
111 */
112 public static int decodeUInt16(final byte[] intbuf, final int offset) {
113 int r = (intbuf[offset] & 0xff) << 8;
114 return r | (intbuf[offset + 1] & 0xff);
115 }
116
117 /**
118 * Convert sequence of 3 bytes (network byte order) into unsigned value.
119 *
120 * @param intbuf
121 * buffer to acquire the 3 bytes of data from.
122 * @param offset
123 * position within the buffer to begin reading from. This
124 * position and the next 2 bytes after it (for a total of 3
125 * bytes) will be read.
126 * @return signed integer value that matches the 24 bits read.
127 * @since 4.9
128 */
129 public static int decodeUInt24(byte[] intbuf, int offset) {
130 int r = (intbuf[offset] & 0xff) << 8;
131 r |= intbuf[offset + 1] & 0xff;
132 return (r << 8) | (intbuf[offset + 2] & 0xff);
133 }
134
135 /**
136 * Convert sequence of 4 bytes (network byte order) into signed value.
137 *
138 * @param intbuf
139 * buffer to acquire the 4 bytes of data from.
140 * @param offset
141 * position within the buffer to begin reading from. This
142 * position and the next 3 bytes after it (for a total of 4
143 * bytes) will be read.
144 * @return signed integer value that matches the 32 bits read.
145 */
146 public static int decodeInt32(final byte[] intbuf, final int offset) {
147 int r = intbuf[offset] << 8;
148
149 r |= intbuf[offset + 1] & 0xff;
150 r <<= 8;
151
152 r |= intbuf[offset + 2] & 0xff;
153 return (r << 8) | (intbuf[offset + 3] & 0xff);
154 }
155
156 /**
157 * Convert sequence of 8 bytes (network byte order) into signed value.
158 *
159 * @param intbuf
160 * buffer to acquire the 8 bytes of data from.
161 * @param offset
162 * position within the buffer to begin reading from. This
163 * position and the next 7 bytes after it (for a total of 8
164 * bytes) will be read.
165 * @return signed integer value that matches the 64 bits read.
166 * @since 3.0
167 */
168 public static long decodeInt64(final byte[] intbuf, final int offset) {
169 long r = intbuf[offset] << 8;
170
171 r |= intbuf[offset + 1] & 0xff;
172 r <<= 8;
173
174 r |= intbuf[offset + 2] & 0xff;
175 r <<= 8;
176
177 r |= intbuf[offset + 3] & 0xff;
178 r <<= 8;
179
180 r |= intbuf[offset + 4] & 0xff;
181 r <<= 8;
182
183 r |= intbuf[offset + 5] & 0xff;
184 r <<= 8;
185
186 r |= intbuf[offset + 6] & 0xff;
187 return (r << 8) | (intbuf[offset + 7] & 0xff);
188 }
189
190 /**
191 * Convert sequence of 4 bytes (network byte order) into unsigned value.
192 *
193 * @param intbuf
194 * buffer to acquire the 4 bytes of data from.
195 * @param offset
196 * position within the buffer to begin reading from. This
197 * position and the next 3 bytes after it (for a total of 4
198 * bytes) will be read.
199 * @return unsigned integer value that matches the 32 bits read.
200 */
201 public static long decodeUInt32(final byte[] intbuf, final int offset) {
202 int low = (intbuf[offset + 1] & 0xff) << 8;
203 low |= (intbuf[offset + 2] & 0xff);
204 low <<= 8;
205
206 low |= (intbuf[offset + 3] & 0xff);
207 return ((long) (intbuf[offset] & 0xff)) << 24 | low;
208 }
209
210 /**
211 * Convert sequence of 8 bytes (network byte order) into unsigned value.
212 *
213 * @param intbuf
214 * buffer to acquire the 8 bytes of data from.
215 * @param offset
216 * position within the buffer to begin reading from. This
217 * position and the next 7 bytes after it (for a total of 8
218 * bytes) will be read.
219 * @return unsigned integer value that matches the 64 bits read.
220 */
221 public static long decodeUInt64(final byte[] intbuf, final int offset) {
222 return (decodeUInt32(intbuf, offset) << 32)
223 | decodeUInt32(intbuf, offset + 4);
224 }
225
226 /**
227 * Write a 16 bit integer as a sequence of 2 bytes (network byte order).
228 *
229 * @param intbuf
230 * buffer to write the 2 bytes of data into.
231 * @param offset
232 * position within the buffer to begin writing to. This position
233 * and the next byte after it (for a total of 2 bytes) will be
234 * replaced.
235 * @param v
236 * the value to write.
237 */
238 public static void encodeInt16(final byte[] intbuf, final int offset, int v) {
239 intbuf[offset + 1] = (byte) v;
240 v >>>= 8;
241
242 intbuf[offset] = (byte) v;
243 }
244
245 /**
246 * Write a 24 bit integer as a sequence of 3 bytes (network byte order).
247 *
248 * @param intbuf
249 * buffer to write the 3 bytes of data into.
250 * @param offset
251 * position within the buffer to begin writing to. This position
252 * and the next 2 bytes after it (for a total of 3 bytes) will be
253 * replaced.
254 * @param v
255 * the value to write.
256 * @since 4.9
257 */
258 public static void encodeInt24(byte[] intbuf, int offset, int v) {
259 intbuf[offset + 2] = (byte) v;
260 v >>>= 8;
261
262 intbuf[offset + 1] = (byte) v;
263 v >>>= 8;
264
265 intbuf[offset] = (byte) v;
266 }
267
268 /**
269 * Write a 32 bit integer as a sequence of 4 bytes (network byte order).
270 *
271 * @param intbuf
272 * buffer to write the 4 bytes of data into.
273 * @param offset
274 * position within the buffer to begin writing to. This position
275 * and the next 3 bytes after it (for a total of 4 bytes) will be
276 * replaced.
277 * @param v
278 * the value to write.
279 */
280 public static void encodeInt32(final byte[] intbuf, final int offset, int v) {
281 intbuf[offset + 3] = (byte) v;
282 v >>>= 8;
283
284 intbuf[offset + 2] = (byte) v;
285 v >>>= 8;
286
287 intbuf[offset + 1] = (byte) v;
288 v >>>= 8;
289
290 intbuf[offset] = (byte) v;
291 }
292
293 /**
294 * Write a 64 bit integer as a sequence of 8 bytes (network byte order).
295 *
296 * @param intbuf
297 * buffer to write the 8 bytes of data into.
298 * @param offset
299 * position within the buffer to begin writing to. This position
300 * and the next 7 bytes after it (for a total of 8 bytes) will be
301 * replaced.
302 * @param v
303 * the value to write.
304 */
305 public static void encodeInt64(final byte[] intbuf, final int offset, long v) {
306 intbuf[offset + 7] = (byte) v;
307 v >>>= 8;
308
309 intbuf[offset + 6] = (byte) v;
310 v >>>= 8;
311
312 intbuf[offset + 5] = (byte) v;
313 v >>>= 8;
314
315 intbuf[offset + 4] = (byte) v;
316 v >>>= 8;
317
318 intbuf[offset + 3] = (byte) v;
319 v >>>= 8;
320
321 intbuf[offset + 2] = (byte) v;
322 v >>>= 8;
323
324 intbuf[offset + 1] = (byte) v;
325 v >>>= 8;
326
327 intbuf[offset] = (byte) v;
328 }
329
330 private NB() {
331 // Don't create instances of a static only utility.
332 }
333 }