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 }