1 /*
2 * Copyright (C) 2008, 2015 Shawn O. Pearce <spearce@spearce.org> and others
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Distribution License v. 1.0 which is available at
6 * https://www.eclipse.org/org/documents/edl-v10.php.
7 *
8 * SPDX-License-Identifier: BSD-3-Clause
9 */
10
11 package org.eclipse.jgit.util;
12
13 /**
14 * Conversion utilities for network byte order handling.
15 */
16 public final class NB {
17 /**
18 * Compare a 32 bit unsigned integer stored in a 32 bit signed integer.
19 * <p>
20 * This function performs an unsigned compare operation, even though Java
21 * does not natively support unsigned integer values. Negative numbers are
22 * treated as larger than positive ones.
23 *
24 * @param a
25 * the first value to compare.
26 * @param b
27 * the second value to compare.
28 * @return < 0 if a < b; 0 if a == b; > 0 if a > b.
29 */
30 public static int compareUInt32(final int a, final int b) {
31 final int cmp = (a >>> 1) - (b >>> 1);
32 if (cmp != 0)
33 return cmp;
34 return (a & 1) - (b & 1);
35 }
36
37 /**
38 * Compare a 64 bit unsigned integer stored in a 64 bit signed integer.
39 * <p>
40 * This function performs an unsigned compare operation, even though Java
41 * does not natively support unsigned integer values. Negative numbers are
42 * treated as larger than positive ones.
43 *
44 * @param a
45 * the first value to compare.
46 * @param b
47 * the second value to compare.
48 * @return < 0 if a < b; 0 if a == b; > 0 if a > b.
49 * @since 4.3
50 */
51 public static int compareUInt64(final long a, final long b) {
52 long cmp = (a >>> 1) - (b >>> 1);
53 if (cmp > 0) {
54 return 1;
55 } else if (cmp < 0) {
56 return -1;
57 }
58 cmp = ((a & 1) - (b & 1));
59 if (cmp > 0) {
60 return 1;
61 } else if (cmp < 0) {
62 return -1;
63 } else {
64 return 0;
65 }
66 }
67
68 /**
69 * Convert sequence of 2 bytes (network byte order) into unsigned value.
70 *
71 * @param intbuf
72 * buffer to acquire the 2 bytes of data from.
73 * @param offset
74 * position within the buffer to begin reading from. This
75 * position and the next byte after it (for a total of 2 bytes)
76 * will be read.
77 * @return unsigned integer value that matches the 16 bits read.
78 */
79 public static int decodeUInt16(final byte[] intbuf, final int offset) {
80 int r = (intbuf[offset] & 0xff) << 8;
81 return r | (intbuf[offset + 1] & 0xff);
82 }
83
84 /**
85 * Convert sequence of 3 bytes (network byte order) into unsigned value.
86 *
87 * @param intbuf
88 * buffer to acquire the 3 bytes of data from.
89 * @param offset
90 * position within the buffer to begin reading from. This
91 * position and the next 2 bytes after it (for a total of 3
92 * bytes) will be read.
93 * @return signed integer value that matches the 24 bits read.
94 * @since 4.9
95 */
96 public static int decodeUInt24(byte[] intbuf, int offset) {
97 int r = (intbuf[offset] & 0xff) << 8;
98 r |= intbuf[offset + 1] & 0xff;
99 return (r << 8) | (intbuf[offset + 2] & 0xff);
100 }
101
102 /**
103 * Convert sequence of 4 bytes (network byte order) into signed value.
104 *
105 * @param intbuf
106 * buffer to acquire the 4 bytes of data from.
107 * @param offset
108 * position within the buffer to begin reading from. This
109 * position and the next 3 bytes after it (for a total of 4
110 * bytes) will be read.
111 * @return signed integer value that matches the 32 bits read.
112 */
113 public static int decodeInt32(final byte[] intbuf, final int offset) {
114 int r = intbuf[offset] << 8;
115
116 r |= intbuf[offset + 1] & 0xff;
117 r <<= 8;
118
119 r |= intbuf[offset + 2] & 0xff;
120 return (r << 8) | (intbuf[offset + 3] & 0xff);
121 }
122
123 /**
124 * Convert sequence of 8 bytes (network byte order) into signed value.
125 *
126 * @param intbuf
127 * buffer to acquire the 8 bytes of data from.
128 * @param offset
129 * position within the buffer to begin reading from. This
130 * position and the next 7 bytes after it (for a total of 8
131 * bytes) will be read.
132 * @return signed integer value that matches the 64 bits read.
133 * @since 3.0
134 */
135 public static long decodeInt64(final byte[] intbuf, final int offset) {
136 long r = intbuf[offset] << 8;
137
138 r |= intbuf[offset + 1] & 0xff;
139 r <<= 8;
140
141 r |= intbuf[offset + 2] & 0xff;
142 r <<= 8;
143
144 r |= intbuf[offset + 3] & 0xff;
145 r <<= 8;
146
147 r |= intbuf[offset + 4] & 0xff;
148 r <<= 8;
149
150 r |= intbuf[offset + 5] & 0xff;
151 r <<= 8;
152
153 r |= intbuf[offset + 6] & 0xff;
154 return (r << 8) | (intbuf[offset + 7] & 0xff);
155 }
156
157 /**
158 * Convert sequence of 4 bytes (network byte order) into unsigned value.
159 *
160 * @param intbuf
161 * buffer to acquire the 4 bytes of data from.
162 * @param offset
163 * position within the buffer to begin reading from. This
164 * position and the next 3 bytes after it (for a total of 4
165 * bytes) will be read.
166 * @return unsigned integer value that matches the 32 bits read.
167 */
168 public static long decodeUInt32(final byte[] intbuf, final int offset) {
169 int low = (intbuf[offset + 1] & 0xff) << 8;
170 low |= (intbuf[offset + 2] & 0xff);
171 low <<= 8;
172
173 low |= (intbuf[offset + 3] & 0xff);
174 return ((long) (intbuf[offset] & 0xff)) << 24 | low;
175 }
176
177 /**
178 * Convert sequence of 8 bytes (network byte order) into unsigned value.
179 *
180 * @param intbuf
181 * buffer to acquire the 8 bytes of data from.
182 * @param offset
183 * position within the buffer to begin reading from. This
184 * position and the next 7 bytes after it (for a total of 8
185 * bytes) will be read.
186 * @return unsigned integer value that matches the 64 bits read.
187 */
188 public static long decodeUInt64(final byte[] intbuf, final int offset) {
189 return (decodeUInt32(intbuf, offset) << 32)
190 | decodeUInt32(intbuf, offset + 4);
191 }
192
193 /**
194 * Write a 16 bit integer as a sequence of 2 bytes (network byte order).
195 *
196 * @param intbuf
197 * buffer to write the 2 bytes of data into.
198 * @param offset
199 * position within the buffer to begin writing to. This position
200 * and the next byte after it (for a total of 2 bytes) will be
201 * replaced.
202 * @param v
203 * the value to write.
204 */
205 public static void encodeInt16(final byte[] intbuf, final int offset, int v) {
206 intbuf[offset + 1] = (byte) v;
207 v >>>= 8;
208
209 intbuf[offset] = (byte) v;
210 }
211
212 /**
213 * Write a 24 bit integer as a sequence of 3 bytes (network byte order).
214 *
215 * @param intbuf
216 * buffer to write the 3 bytes of data into.
217 * @param offset
218 * position within the buffer to begin writing to. This position
219 * and the next 2 bytes after it (for a total of 3 bytes) will be
220 * replaced.
221 * @param v
222 * the value to write.
223 * @since 4.9
224 */
225 public static void encodeInt24(byte[] intbuf, int offset, int v) {
226 intbuf[offset + 2] = (byte) v;
227 v >>>= 8;
228
229 intbuf[offset + 1] = (byte) v;
230 v >>>= 8;
231
232 intbuf[offset] = (byte) v;
233 }
234
235 /**
236 * Write a 32 bit integer as a sequence of 4 bytes (network byte order).
237 *
238 * @param intbuf
239 * buffer to write the 4 bytes of data into.
240 * @param offset
241 * position within the buffer to begin writing to. This position
242 * and the next 3 bytes after it (for a total of 4 bytes) will be
243 * replaced.
244 * @param v
245 * the value to write.
246 */
247 public static void encodeInt32(final byte[] intbuf, final int offset, int v) {
248 intbuf[offset + 3] = (byte) v;
249 v >>>= 8;
250
251 intbuf[offset + 2] = (byte) v;
252 v >>>= 8;
253
254 intbuf[offset + 1] = (byte) v;
255 v >>>= 8;
256
257 intbuf[offset] = (byte) v;
258 }
259
260 /**
261 * Write a 64 bit integer as a sequence of 8 bytes (network byte order).
262 *
263 * @param intbuf
264 * buffer to write the 8 bytes of data into.
265 * @param offset
266 * position within the buffer to begin writing to. This position
267 * and the next 7 bytes after it (for a total of 8 bytes) will be
268 * replaced.
269 * @param v
270 * the value to write.
271 */
272 public static void encodeInt64(final byte[] intbuf, final int offset, long v) {
273 intbuf[offset + 7] = (byte) v;
274 v >>>= 8;
275
276 intbuf[offset + 6] = (byte) v;
277 v >>>= 8;
278
279 intbuf[offset + 5] = (byte) v;
280 v >>>= 8;
281
282 intbuf[offset + 4] = (byte) v;
283 v >>>= 8;
284
285 intbuf[offset + 3] = (byte) v;
286 v >>>= 8;
287
288 intbuf[offset + 2] = (byte) v;
289 v >>>= 8;
290
291 intbuf[offset + 1] = (byte) v;
292 v >>>= 8;
293
294 intbuf[offset] = (byte) v;
295 }
296
297 private NB() {
298 // Don't create instances of a static only utility.
299 }
300 }