NB.java

  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. package org.eclipse.jgit.util;

  11. /**
  12.  * Conversion utilities for network byte order handling.
  13.  */
  14. public final class NB {
  15.     /**
  16.      * Compare a 32 bit unsigned integer stored in a 32 bit signed integer.
  17.      * <p>
  18.      * This function performs an unsigned compare operation, even though Java
  19.      * does not natively support unsigned integer values. Negative numbers are
  20.      * treated as larger than positive ones.
  21.      *
  22.      * @param a
  23.      *            the first value to compare.
  24.      * @param b
  25.      *            the second value to compare.
  26.      * @return &lt; 0 if a &lt; b; 0 if a == b; &gt; 0 if a &gt; b.
  27.      */
  28.     public static int compareUInt32(final int a, final int b) {
  29.         final int cmp = (a >>> 1) - (b >>> 1);
  30.         if (cmp != 0)
  31.             return cmp;
  32.         return (a & 1) - (b & 1);
  33.     }

  34.     /**
  35.      * Compare a 64 bit unsigned integer stored in a 64 bit signed integer.
  36.      * <p>
  37.      * This function performs an unsigned compare operation, even though Java
  38.      * does not natively support unsigned integer values. Negative numbers are
  39.      * treated as larger than positive ones.
  40.      *
  41.      * @param a
  42.      *            the first value to compare.
  43.      * @param b
  44.      *            the second value to compare.
  45.      * @return &lt; 0 if a &lt; b; 0 if a == b; &gt; 0 if a &gt; b.
  46.      * @since 4.3
  47.      */
  48.     public static int compareUInt64(final long a, final long b) {
  49.         long cmp = (a >>> 1) - (b >>> 1);
  50.         if (cmp > 0) {
  51.             return 1;
  52.         } else if (cmp < 0) {
  53.             return -1;
  54.         }
  55.         cmp = ((a & 1) - (b & 1));
  56.         if (cmp > 0) {
  57.             return 1;
  58.         } else if (cmp < 0) {
  59.             return -1;
  60.         } else {
  61.             return 0;
  62.         }
  63.     }

  64.     /**
  65.      * Convert sequence of 2 bytes (network byte order) into unsigned value.
  66.      *
  67.      * @param intbuf
  68.      *            buffer to acquire the 2 bytes of data from.
  69.      * @param offset
  70.      *            position within the buffer to begin reading from. This
  71.      *            position and the next byte after it (for a total of 2 bytes)
  72.      *            will be read.
  73.      * @return unsigned integer value that matches the 16 bits read.
  74.      */
  75.     public static int decodeUInt16(final byte[] intbuf, final int offset) {
  76.         int r = (intbuf[offset] & 0xff) << 8;
  77.         return r | (intbuf[offset + 1] & 0xff);
  78.     }

  79.     /**
  80.      * Convert sequence of 3 bytes (network byte order) into unsigned value.
  81.      *
  82.      * @param intbuf
  83.      *            buffer to acquire the 3 bytes of data from.
  84.      * @param offset
  85.      *            position within the buffer to begin reading from. This
  86.      *            position and the next 2 bytes after it (for a total of 3
  87.      *            bytes) will be read.
  88.      * @return signed integer value that matches the 24 bits read.
  89.      * @since 4.9
  90.      */
  91.     public static int decodeUInt24(byte[] intbuf, int offset) {
  92.         int r = (intbuf[offset] & 0xff) << 8;
  93.         r |= intbuf[offset + 1] & 0xff;
  94.         return (r << 8) | (intbuf[offset + 2] & 0xff);
  95.     }

  96.     /**
  97.      * Convert sequence of 4 bytes (network byte order) into signed value.
  98.      *
  99.      * @param intbuf
  100.      *            buffer to acquire the 4 bytes of data from.
  101.      * @param offset
  102.      *            position within the buffer to begin reading from. This
  103.      *            position and the next 3 bytes after it (for a total of 4
  104.      *            bytes) will be read.
  105.      * @return signed integer value that matches the 32 bits read.
  106.      */
  107.     public static int decodeInt32(final byte[] intbuf, final int offset) {
  108.         int r = intbuf[offset] << 8;

  109.         r |= intbuf[offset + 1] & 0xff;
  110.         r <<= 8;

  111.         r |= intbuf[offset + 2] & 0xff;
  112.         return (r << 8) | (intbuf[offset + 3] & 0xff);
  113.     }

  114.     /**
  115.      * Convert sequence of 8 bytes (network byte order) into signed value.
  116.      *
  117.      * @param intbuf
  118.      *            buffer to acquire the 8 bytes of data from.
  119.      * @param offset
  120.      *            position within the buffer to begin reading from. This
  121.      *            position and the next 7 bytes after it (for a total of 8
  122.      *            bytes) will be read.
  123.      * @return signed integer value that matches the 64 bits read.
  124.      * @since 3.0
  125.      */
  126.     public static long decodeInt64(final byte[] intbuf, final int offset) {
  127.         long r = intbuf[offset] << 8;

  128.         r |= intbuf[offset + 1] & 0xff;
  129.         r <<= 8;

  130.         r |= intbuf[offset + 2] & 0xff;
  131.         r <<= 8;

  132.         r |= intbuf[offset + 3] & 0xff;
  133.         r <<= 8;

  134.         r |= intbuf[offset + 4] & 0xff;
  135.         r <<= 8;

  136.         r |= intbuf[offset + 5] & 0xff;
  137.         r <<= 8;

  138.         r |= intbuf[offset + 6] & 0xff;
  139.         return (r << 8) | (intbuf[offset + 7] & 0xff);
  140.     }

  141.     /**
  142.      * Convert sequence of 4 bytes (network byte order) into unsigned value.
  143.      *
  144.      * @param intbuf
  145.      *            buffer to acquire the 4 bytes of data from.
  146.      * @param offset
  147.      *            position within the buffer to begin reading from. This
  148.      *            position and the next 3 bytes after it (for a total of 4
  149.      *            bytes) will be read.
  150.      * @return unsigned integer value that matches the 32 bits read.
  151.      */
  152.     public static long decodeUInt32(final byte[] intbuf, final int offset) {
  153.         int low = (intbuf[offset + 1] & 0xff) << 8;
  154.         low |= (intbuf[offset + 2] & 0xff);
  155.         low <<= 8;

  156.         low |= (intbuf[offset + 3] & 0xff);
  157.         return ((long) (intbuf[offset] & 0xff)) << 24 | low;
  158.     }

  159.     /**
  160.      * Convert sequence of 8 bytes (network byte order) into unsigned value.
  161.      *
  162.      * @param intbuf
  163.      *            buffer to acquire the 8 bytes of data from.
  164.      * @param offset
  165.      *            position within the buffer to begin reading from. This
  166.      *            position and the next 7 bytes after it (for a total of 8
  167.      *            bytes) will be read.
  168.      * @return unsigned integer value that matches the 64 bits read.
  169.      */
  170.     public static long decodeUInt64(final byte[] intbuf, final int offset) {
  171.         return (decodeUInt32(intbuf, offset) << 32)
  172.                 | decodeUInt32(intbuf, offset + 4);
  173.     }

  174.     /**
  175.      * Write a 16 bit integer as a sequence of 2 bytes (network byte order).
  176.      *
  177.      * @param intbuf
  178.      *            buffer to write the 2 bytes of data into.
  179.      * @param offset
  180.      *            position within the buffer to begin writing to. This position
  181.      *            and the next byte after it (for a total of 2 bytes) will be
  182.      *            replaced.
  183.      * @param v
  184.      *            the value to write.
  185.      */
  186.     public static void encodeInt16(final byte[] intbuf, final int offset, int v) {
  187.         intbuf[offset + 1] = (byte) v;
  188.         v >>>= 8;

  189.         intbuf[offset] = (byte) v;
  190.     }

  191.     /**
  192.      * Write a 24 bit integer as a sequence of 3 bytes (network byte order).
  193.      *
  194.      * @param intbuf
  195.      *            buffer to write the 3 bytes of data into.
  196.      * @param offset
  197.      *            position within the buffer to begin writing to. This position
  198.      *            and the next 2 bytes after it (for a total of 3 bytes) will be
  199.      *            replaced.
  200.      * @param v
  201.      *            the value to write.
  202.      * @since 4.9
  203.      */
  204.     public static void encodeInt24(byte[] intbuf, int offset, int v) {
  205.         intbuf[offset + 2] = (byte) v;
  206.         v >>>= 8;

  207.         intbuf[offset + 1] = (byte) v;
  208.         v >>>= 8;

  209.         intbuf[offset] = (byte) v;
  210.     }

  211.     /**
  212.      * Write a 32 bit integer as a sequence of 4 bytes (network byte order).
  213.      *
  214.      * @param intbuf
  215.      *            buffer to write the 4 bytes of data into.
  216.      * @param offset
  217.      *            position within the buffer to begin writing to. This position
  218.      *            and the next 3 bytes after it (for a total of 4 bytes) will be
  219.      *            replaced.
  220.      * @param v
  221.      *            the value to write.
  222.      */
  223.     public static void encodeInt32(final byte[] intbuf, final int offset, int v) {
  224.         intbuf[offset + 3] = (byte) v;
  225.         v >>>= 8;

  226.         intbuf[offset + 2] = (byte) v;
  227.         v >>>= 8;

  228.         intbuf[offset + 1] = (byte) v;
  229.         v >>>= 8;

  230.         intbuf[offset] = (byte) v;
  231.     }

  232.     /**
  233.      * Write a 64 bit integer as a sequence of 8 bytes (network byte order).
  234.      *
  235.      * @param intbuf
  236.      *            buffer to write the 8 bytes of data into.
  237.      * @param offset
  238.      *            position within the buffer to begin writing to. This position
  239.      *            and the next 7 bytes after it (for a total of 8 bytes) will be
  240.      *            replaced.
  241.      * @param v
  242.      *            the value to write.
  243.      */
  244.     public static void encodeInt64(final byte[] intbuf, final int offset, long v) {
  245.         intbuf[offset + 7] = (byte) v;
  246.         v >>>= 8;

  247.         intbuf[offset + 6] = (byte) v;
  248.         v >>>= 8;

  249.         intbuf[offset + 5] = (byte) v;
  250.         v >>>= 8;

  251.         intbuf[offset + 4] = (byte) v;
  252.         v >>>= 8;

  253.         intbuf[offset + 3] = (byte) v;
  254.         v >>>= 8;

  255.         intbuf[offset + 2] = (byte) v;
  256.         v >>>= 8;

  257.         intbuf[offset + 1] = (byte) v;
  258.         v >>>= 8;

  259.         intbuf[offset] = (byte) v;
  260.     }

  261.     private NB() {
  262.         // Don't create instances of a static only utility.
  263.     }
  264. }