View Javadoc
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 &lt; 0 if a &lt; b; 0 if a == b; &gt; 0 if a &gt; 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 &lt; 0 if a &lt; b; 0 if a == b; &gt; 0 if a &gt; 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 }