All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.activemq.artemis.utils.ByteUtil Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 35.0.0.Beta1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.utils;

import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import io.netty.buffer.ByteBuf;
import io.netty.util.internal.PlatformDependent;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.logs.ActiveMQUtilBundle;
import org.jboss.logging.Logger;

public class ByteUtil {

   public static final String NON_ASCII_STRING = "@@@@@";

   private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
   private static final String prefix = "^\\s*(\\d+)\\s*";
   private static final String suffix = "(b)?\\s*$";
   private static final Pattern ONE = Pattern.compile(prefix + suffix, Pattern.CASE_INSENSITIVE);
   private static final Pattern KILO = Pattern.compile(prefix + "k" + suffix, Pattern.CASE_INSENSITIVE);
   private static final Pattern MEGA = Pattern.compile(prefix + "m" + suffix, Pattern.CASE_INSENSITIVE);
   private static final Pattern GIGA = Pattern.compile(prefix + "g" + suffix, Pattern.CASE_INSENSITIVE);

   public static void debugFrame(Logger logger, String message, ByteBuf byteIn) {
      if (logger.isTraceEnabled()) {
         int location = byteIn.readerIndex();
         // debugging
         byte[] frame = new byte[byteIn.writerIndex()];
         byteIn.readBytes(frame);

         try {
            logger.trace(message + "\n" + ByteUtil.formatGroup(ByteUtil.bytesToHex(frame), 8, 16));
         } catch (Exception e) {
            logger.warn(e.getMessage(), e);
         }

         byteIn.readerIndex(location);
      }
   }

   public static String formatGroup(String str, int groupSize, int lineBreak) {
      StringBuffer buffer = new StringBuffer();

      int line = 1;
      buffer.append("/*  1 */ \"");
      for (int i = 0; i < str.length(); i += groupSize) {
         buffer.append(str.substring(i, i + Math.min(str.length() - i, groupSize)));

         if ((i + groupSize) % lineBreak == 0) {
            buffer.append("\" +\n/* ");
            line++;
            if (line < 10) {
               buffer.append(" ");
            }
            buffer.append(Integer.toString(line) + " */ \"");
         } else if ((i + groupSize) % groupSize == 0 && str.length() - i > groupSize) {
            buffer.append("\" + \"");
         }
      }

      buffer.append("\";");

      return buffer.toString();

   }

   public static String maxString(String value, int size) {
      if (value.length() < size) {
         return value;
      } else {
         return value.substring(0, size / 2) + " ... " + value.substring(value.length() - size / 2);
      }
   }

   public static String bytesToHex(byte[] bytes) {
      char[] hexChars = new char[bytes.length * 2];
      for (int j = 0; j < bytes.length; j++) {
         int v = bytes[j] & 0xFF;
         hexChars[j * 2] = hexArray[v >>> 4];
         hexChars[j * 2 + 1] = hexArray[v & 0x0F];
      }
      return new String(hexChars);
   }

   public static String bytesToHex(byte[] bytes, int groupSize) {
      if (bytes == null) {
         return "NULL";
      }

      if (bytes.length == 0) {
         return "[]";
      }

      char[] hexChars = new char[bytes.length * 2 + numberOfGroups(bytes, groupSize)];
      int outPos = 0;
      for (int j = 0; j < bytes.length; j++) {
         if (j > 0 && j % groupSize == 0) {
            hexChars[outPos++] = ' ';
         }
         int v = bytes[j] & 0xFF;
         hexChars[outPos++] = hexArray[v >>> 4];
         hexChars[outPos++] = hexArray[v & 0x0F];
      }
      return new String(hexChars);
   }

   public static String toSimpleString(byte[] bytes) {
      SimpleString simpleString = new SimpleString(bytes);
      String value = simpleString.toString();

      for (char c : value.toCharArray()) {
         if (c < ' ' || c > 127) {
            return NON_ASCII_STRING;
         }
      }

      return value;
   }

   private static int numberOfGroups(byte[] bytes, int groupSize) {
      int groups = bytes.length / groupSize;

      if (bytes.length % groupSize == 0) {
         groups--;
      }

      return groups;
   }

   public static final byte[] intToBytes(int value) {
      return new byte[] {
         (byte)(value >>> 24),
         (byte)(value >>> 16),
         (byte)(value >>> 8),
         (byte)value
      };
   }

   public static int bytesToInt(byte[] b) {
      return ((int) b[3] & 0xff)
            | ((int) b[2] & 0xff) << 8
            | ((int) b[1] & 0xff) << 16
            | ((int) b[0] & 0xff) << 24;
   }

   public static byte[] hexToBytes(String hexStr) {
      byte[] bytes = new byte[hexStr.length() / 2];
      for (int i = 0; i < bytes.length; i++) {
         bytes[i] = (byte) Integer.parseInt(hexStr.substring(2 * i, 2 * i + 2), 16);
      }
      return bytes;
   }

   public static String readLine(ActiveMQBuffer buffer) {
      StringBuilder sb = new StringBuilder("");
      char c = buffer.readChar();
      while (c != '\n') {
         sb.append(c);
         c = buffer.readChar();
      }
      return sb.toString();
   }

   public static byte[] getActiveArray(ByteBuffer buffer) {
      byte[] ret = new byte[buffer.remaining()];
      if (buffer.hasArray()) {
         byte[] array = buffer.array();
         System.arraycopy(array, buffer.arrayOffset() + buffer.position(), ret, 0, ret.length);
      } else {
         buffer.slice().get(ret);
      }
      return ret;
   }

   public static long convertTextBytes(final String text) {
      try {
         Matcher m = ONE.matcher(text);
         if (m.matches()) {
            return Long.valueOf(Long.parseLong(m.group(1)));
         }

         m = KILO.matcher(text);
         if (m.matches()) {
            return Long.valueOf(Long.parseLong(m.group(1)) * 1024);
         }

         m = MEGA.matcher(text);
         if (m.matches()) {
            return Long.valueOf(Long.parseLong(m.group(1)) * 1024 * 1024);
         }

         m = GIGA.matcher(text);
         if (m.matches()) {
            return Long.valueOf(Long.parseLong(m.group(1)) * 1024 * 1024 * 1024);
         }

         return Long.parseLong(text);
      } catch (NumberFormatException e) {
         throw ActiveMQUtilBundle.BUNDLE.failedToParseLong(text);
      }
   }

   public static boolean equals(final byte[] left, final byte[] right) {
      return equals(left, right, 0, right.length);
   }

   public static boolean equals(final byte[] left,
                                final byte[] right,
                                final int rightOffset,
                                final int rightLength) {
      if (left == right)
         return true;
      if (left == null || right == null)
         return false;
      if (left.length != rightLength)
         return false;
      if (PlatformDependent.isUnaligned() && PlatformDependent.hasUnsafe()) {
         return equalsUnsafe(left, right, rightOffset, rightLength);
      } else {
         return equalsSafe(left, right, rightOffset, rightLength);
      }
   }

   private static boolean equalsSafe(byte[] left, byte[] right, int rightOffset, int rightLength) {
      for (int i = 0; i < rightLength; i++)
         if (left[i] != right[rightOffset + i])
            return false;
      return true;
   }

   private static boolean equalsUnsafe(final byte[] left,
                                       final byte[] right,
                                       final int rightOffset,
                                       final int rightLength) {
      final int longCount = rightLength >>> 3;
      final int bytesCount = rightLength & 7;
      int bytesIndex = rightOffset;
      int charsIndex = 0;
      for (int i = 0; i < longCount; i++) {
         final long charsLong = PlatformDependent.getLong(left, charsIndex);
         final long bytesLong = PlatformDependent.getLong(right, bytesIndex);
         if (charsLong != bytesLong) {
            return false;
         }
         bytesIndex += 8;
         charsIndex += 8;
      }
      for (int i = 0; i < bytesCount; i++) {
         final byte charsByte = PlatformDependent.getByte(left, charsIndex);
         final byte bytesByte = PlatformDependent.getByte(right, bytesIndex);
         if (charsByte != bytesByte) {
            return false;
         }
         bytesIndex++;
         charsIndex++;
      }
      return true;
   }


   /**
    * Returns {@code true} if  the {@link SimpleString} encoded content into {@code bytes} is equals to {@code s},
    * {@code false} otherwise.
    * 

* It assumes that the {@code bytes} content is read using {@link SimpleString#readSimpleString(ByteBuf, int)} ie starting right after the * length field. */ public static boolean equals(final byte[] bytes, final ByteBuf byteBuf, final int offset, final int length) { if (bytes.length != length) return false; if (PlatformDependent.isUnaligned() && PlatformDependent.hasUnsafe()) { if ((offset + length) > byteBuf.writerIndex()) { throw new IndexOutOfBoundsException(); } if (byteBuf.hasArray()) { return equals(bytes, byteBuf.array(), byteBuf.arrayOffset() + offset, length); } else if (byteBuf.hasMemoryAddress()) { return equalsOffHeap(bytes, byteBuf.memoryAddress(), offset, length); } } return equalsOnHeap(bytes, byteBuf, offset, length); } private static boolean equalsOnHeap(final byte[] bytes, final ByteBuf byteBuf, final int offset, final int length) { if (bytes.length != length) return false; for (int i = 0; i < length; i++) if (bytes[i] != byteBuf.getByte(offset + i)) return false; return true; } private static boolean equalsOffHeap(final byte[] bytes, final long address, final int offset, final int length) { final int longCount = length >>> 3; final int bytesCount = length & 7; long bytesAddress = address + offset; int charsIndex = 0; for (int i = 0; i < longCount; i++) { final long charsLong = PlatformDependent.getLong(bytes, charsIndex); final long bytesLong = PlatformDependent.getLong(bytesAddress); if (charsLong != bytesLong) { return false; } bytesAddress += 8; charsIndex += 8; } for (int i = 0; i < bytesCount; i++) { final byte charsByte = PlatformDependent.getByte(bytes, charsIndex); final byte bytesByte = PlatformDependent.getByte(bytesAddress); if (charsByte != bytesByte) { return false; } bytesAddress++; charsIndex++; } return true; } public static int intFromBytes(byte b1, byte b2, byte b3, byte b4) { return b1 << 24 | (b2 & 0xFF) << 16 | (b3 & 0xFF) << 8 | (b4 & 0xFF); } /** * It zeroes the whole {@link ByteBuffer#capacity()} of the given {@code buffer}. * * @throws ReadOnlyBufferException if {@code buffer} is read-only */ public static void zeros(final ByteBuffer buffer) { uncheckedZeros(buffer, 0, buffer.capacity()); } /** * It zeroes {@code bytes} of the given {@code buffer}, starting (inclusive) from {@code offset}. * * @throws IndexOutOfBoundsException if {@code offset + bytes > }{@link ByteBuffer#capacity()} or {@code offset >= }{@link ByteBuffer#capacity()} * @throws IllegalArgumentException if {@code offset} or {@code capacity} are less then 0 * @throws ReadOnlyBufferException if {@code buffer} is read-only */ public static void zeros(final ByteBuffer buffer, int offset, int bytes) { if (offset < 0 || bytes < 0) { throw new IllegalArgumentException(); } final int capacity = buffer.capacity(); if (offset >= capacity || (offset + bytes) > capacity) { throw new IndexOutOfBoundsException(); } uncheckedZeros(buffer, offset, bytes); } private static void uncheckedZeros(final ByteBuffer buffer, int offset, int bytes) { if (buffer.isReadOnly()) { throw new ReadOnlyBufferException(); } final byte zero = (byte) 0; if (buffer.isDirect() && PlatformDependent.hasUnsafe()) { PlatformDependent.setMemory(PlatformDependent.directBufferAddress(buffer) + offset, bytes, zero); } else if (buffer.hasArray()) { //SIMD OPTIMIZATION final int arrayOffset = buffer.arrayOffset(); final int start = arrayOffset + offset; Arrays.fill(buffer.array(), start, start + bytes, zero); } else { //slow path for (int i = 0; i < bytes; i++) { buffer.put(i + offset, zero); } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy