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 }