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 /** Conversion utilities for network byte order handling. */ 47 public final class NB { 48 /** 49 * Compare a 32 bit unsigned integer stored in a 32 bit signed integer. 50 * <p> 51 * This function performs an unsigned compare operation, even though Java 52 * does not natively support unsigned integer values. Negative numbers are 53 * treated as larger than positive ones. 54 * 55 * @param a 56 * the first value to compare. 57 * @param b 58 * the second value to compare. 59 * @return < 0 if a < b; 0 if a == b; > 0 if a > b. 60 */ 61 public static int compareUInt32(final int a, final int b) { 62 final int cmp = (a >>> 1) - (b >>> 1); 63 if (cmp != 0) 64 return cmp; 65 return (a & 1) - (b & 1); 66 } 67 68 /** 69 * Compare a 64 bit unsigned integer stored in a 64 bit signed integer. 70 * <p> 71 * This function performs an unsigned compare operation, even though Java 72 * does not natively support unsigned integer values. Negative numbers are 73 * treated as larger than positive ones. 74 * 75 * @param a 76 * the first value to compare. 77 * @param b 78 * the second value to compare. 79 * @return < 0 if a < b; 0 if a == b; > 0 if a > b. 80 * @since 4.3 81 */ 82 public static int compareUInt64(final long a, final long b) { 83 long cmp = (a >>> 1) - (b >>> 1); 84 if (cmp > 0) { 85 return 1; 86 } else if (cmp < 0) { 87 return -1; 88 } 89 cmp = ((a & 1) - (b & 1)); 90 if (cmp > 0) { 91 return 1; 92 } else if (cmp < 0) { 93 return -1; 94 } else { 95 return 0; 96 } 97 } 98 99 /** 100 * Convert sequence of 2 bytes (network byte order) into unsigned value. 101 * 102 * @param intbuf 103 * buffer to acquire the 2 bytes of data from. 104 * @param offset 105 * position within the buffer to begin reading from. This 106 * position and the next byte after it (for a total of 2 bytes) 107 * will be read. 108 * @return unsigned integer value that matches the 16 bits read. 109 */ 110 public static int decodeUInt16(final byte[] intbuf, final int offset) { 111 int r = (intbuf[offset] & 0xff) << 8; 112 return r | (intbuf[offset + 1] & 0xff); 113 } 114 115 /** 116 * Convert sequence of 3 bytes (network byte order) into unsigned value. 117 * 118 * @param intbuf 119 * buffer to acquire the 3 bytes of data from. 120 * @param offset 121 * position within the buffer to begin reading from. This 122 * position and the next 2 bytes after it (for a total of 3 123 * bytes) will be read. 124 * @return signed integer value that matches the 24 bits read. 125 * @since 4.9 126 */ 127 public static int decodeUInt24(byte[] intbuf, int offset) { 128 int r = (intbuf[offset] & 0xff) << 8; 129 r |= intbuf[offset + 1] & 0xff; 130 return (r << 8) | (intbuf[offset + 2] & 0xff); 131 } 132 133 /** 134 * Convert sequence of 4 bytes (network byte order) into signed value. 135 * 136 * @param intbuf 137 * buffer to acquire the 4 bytes of data from. 138 * @param offset 139 * position within the buffer to begin reading from. This 140 * position and the next 3 bytes after it (for a total of 4 141 * bytes) will be read. 142 * @return signed integer value that matches the 32 bits read. 143 */ 144 public static int decodeInt32(final byte[] intbuf, final int offset) { 145 int r = intbuf[offset] << 8; 146 147 r |= intbuf[offset + 1] & 0xff; 148 r <<= 8; 149 150 r |= intbuf[offset + 2] & 0xff; 151 return (r << 8) | (intbuf[offset + 3] & 0xff); 152 } 153 154 /** 155 * Convert sequence of 8 bytes (network byte order) into signed value. 156 * 157 * @param intbuf 158 * buffer to acquire the 8 bytes of data from. 159 * @param offset 160 * position within the buffer to begin reading from. This 161 * position and the next 7 bytes after it (for a total of 8 162 * bytes) will be read. 163 * @return signed integer value that matches the 64 bits read. 164 * @since 3.0 165 */ 166 public static long decodeInt64(final byte[] intbuf, final int offset) { 167 long r = intbuf[offset] << 8; 168 169 r |= intbuf[offset + 1] & 0xff; 170 r <<= 8; 171 172 r |= intbuf[offset + 2] & 0xff; 173 r <<= 8; 174 175 r |= intbuf[offset + 3] & 0xff; 176 r <<= 8; 177 178 r |= intbuf[offset + 4] & 0xff; 179 r <<= 8; 180 181 r |= intbuf[offset + 5] & 0xff; 182 r <<= 8; 183 184 r |= intbuf[offset + 6] & 0xff; 185 return (r << 8) | (intbuf[offset + 7] & 0xff); 186 } 187 188 /** 189 * Convert sequence of 4 bytes (network byte order) into unsigned value. 190 * 191 * @param intbuf 192 * buffer to acquire the 4 bytes of data from. 193 * @param offset 194 * position within the buffer to begin reading from. This 195 * position and the next 3 bytes after it (for a total of 4 196 * bytes) will be read. 197 * @return unsigned integer value that matches the 32 bits read. 198 */ 199 public static long decodeUInt32(final byte[] intbuf, final int offset) { 200 int low = (intbuf[offset + 1] & 0xff) << 8; 201 low |= (intbuf[offset + 2] & 0xff); 202 low <<= 8; 203 204 low |= (intbuf[offset + 3] & 0xff); 205 return ((long) (intbuf[offset] & 0xff)) << 24 | low; 206 } 207 208 /** 209 * Convert sequence of 8 bytes (network byte order) into unsigned value. 210 * 211 * @param intbuf 212 * buffer to acquire the 8 bytes of data from. 213 * @param offset 214 * position within the buffer to begin reading from. This 215 * position and the next 7 bytes after it (for a total of 8 216 * bytes) will be read. 217 * @return unsigned integer value that matches the 64 bits read. 218 */ 219 public static long decodeUInt64(final byte[] intbuf, final int offset) { 220 return (decodeUInt32(intbuf, offset) << 32) 221 | decodeUInt32(intbuf, offset + 4); 222 } 223 224 /** 225 * Write a 16 bit integer as a sequence of 2 bytes (network byte order). 226 * 227 * @param intbuf 228 * buffer to write the 2 bytes of data into. 229 * @param offset 230 * position within the buffer to begin writing to. This position 231 * and the next byte after it (for a total of 2 bytes) will be 232 * replaced. 233 * @param v 234 * the value to write. 235 */ 236 public static void encodeInt16(final byte[] intbuf, final int offset, int v) { 237 intbuf[offset + 1] = (byte) v; 238 v >>>= 8; 239 240 intbuf[offset] = (byte) v; 241 } 242 243 /** 244 * Write a 24 bit integer as a sequence of 3 bytes (network byte order). 245 * 246 * @param intbuf 247 * buffer to write the 3 bytes of data into. 248 * @param offset 249 * position within the buffer to begin writing to. This position 250 * and the next 2 bytes after it (for a total of 3 bytes) will be 251 * replaced. 252 * @param v 253 * the value to write. 254 * @since 4.9 255 */ 256 public static void encodeInt24(byte[] intbuf, int offset, int v) { 257 intbuf[offset + 2] = (byte) v; 258 v >>>= 8; 259 260 intbuf[offset + 1] = (byte) v; 261 v >>>= 8; 262 263 intbuf[offset] = (byte) v; 264 } 265 266 /** 267 * Write a 32 bit integer as a sequence of 4 bytes (network byte order). 268 * 269 * @param intbuf 270 * buffer to write the 4 bytes of data into. 271 * @param offset 272 * position within the buffer to begin writing to. This position 273 * and the next 3 bytes after it (for a total of 4 bytes) will be 274 * replaced. 275 * @param v 276 * the value to write. 277 */ 278 public static void encodeInt32(final byte[] intbuf, final int offset, int v) { 279 intbuf[offset + 3] = (byte) v; 280 v >>>= 8; 281 282 intbuf[offset + 2] = (byte) v; 283 v >>>= 8; 284 285 intbuf[offset + 1] = (byte) v; 286 v >>>= 8; 287 288 intbuf[offset] = (byte) v; 289 } 290 291 /** 292 * Write a 64 bit integer as a sequence of 8 bytes (network byte order). 293 * 294 * @param intbuf 295 * buffer to write the 8 bytes of data into. 296 * @param offset 297 * position within the buffer to begin writing to. This position 298 * and the next 7 bytes after it (for a total of 8 bytes) will be 299 * replaced. 300 * @param v 301 * the value to write. 302 */ 303 public static void encodeInt64(final byte[] intbuf, final int offset, long v) { 304 intbuf[offset + 7] = (byte) v; 305 v >>>= 8; 306 307 intbuf[offset + 6] = (byte) v; 308 v >>>= 8; 309 310 intbuf[offset + 5] = (byte) v; 311 v >>>= 8; 312 313 intbuf[offset + 4] = (byte) v; 314 v >>>= 8; 315 316 intbuf[offset + 3] = (byte) v; 317 v >>>= 8; 318 319 intbuf[offset + 2] = (byte) v; 320 v >>>= 8; 321 322 intbuf[offset + 1] = (byte) v; 323 v >>>= 8; 324 325 intbuf[offset] = (byte) v; 326 } 327 328 private NB() { 329 // Don't create instances of a static only utility. 330 } 331 }