package com.zaxxer.hikari.json.util;

import java.lang.reflect.Field;

import sun.misc.Unsafe;

public final class Utf8Utils
{
   private static final Unsafe unsafe;
   private static final long fieldOffset;

   static
   {
      unsafe = UnsafeHelper.getUnsafe();
      try {
         Field valueField = String.class.getDeclaredField("value");
         fieldOffset = unsafe.objectFieldOffset(valueField);
      }
      catch (NoSuchFieldException | SecurityException e) {
         throw new RuntimeException("sun.misc.Unsafe not available");
      }
   }

   private Utf8Utils() {
      // utility class
   }

   public static int findEndQuote(final byte[] array, int index)
   {
      for (; index < array.length; index++) {
         if (array[index] == 0x22 /* quote */ && array[index - 1] != 0x5c /* backslash */) {
            return index;
         }
      }

      return -1; // we ran out of data
   }

   public static int findEndQuoteAndHash(final byte[] array, int index, final MutableInteger hash)
   {
      for (;index < array.length; index++) {
         final int c = array[index];
         if (c == 0x22 /* quote */ && array[index - 1] != 0x5c /* backslash */) {
            return index;
         }
         hash.value = 31 * hash.value + c;
      }

      return -1; // we ran out of data
   }

   public static int findEndQuoteUTF8(final byte[] array, int index, final MutableBoolean utf8Detected)
   {
      for (; index < array.length; index++) {
         if (array[index] == 0x22 /* quote */ && array[index - 1] != 0x5c /* backslash */) {
            return index;
         }
         else if (array[index] < 0 && !utf8Detected.bool) {
            utf8Detected.bool = true;
         }
      }

      return -1; // we ran out of data
   }

   public static int seekBackUtf8Boundary(final byte[] array, int index)
   {
      for (; index > 0; index--) {
         final int currentChar = array[index];
         if (currentChar >= 0) {
            return index;
         }
         else if (currentChar >> 5 == 0b110 || currentChar >> 4 == 0b1110 || currentChar >> 5 == 0b11110) {
            return index;
         }
      }

      return 0;
   }

   public static String fastTrackAsciiDecode(final byte[] buf, final int offset, final int length)
   {
      final char[] chars = new char[length];
      for (int i = 0; i < length; i++) {
         chars[i] = (char) buf[offset + i];
      }

      final String s = new String();
      unsafe.putObject(s, fieldOffset, chars);
      return s;
   }
}

@@ -2260,24 +2260,26 @@
 ength)%0A   %7B%0A
+//
       final 
@@ -2311,16 +2311,18 @@
 ength%5D;%0A
+//
       fo
@@ -2350,24 +2350,26 @@
 gth; i++) %7B%0A
+//
          cha
@@ -2400,16 +2400,18 @@
 t + i%5D;%0A
+//
       %7D%0A
@@ -2445,24 +2445,46 @@
  String(
+buf, 0, offset, length
 );%0A     
  unsafe.
@@ -2471,24 +2471,27 @@
 ngth);%0A     
+ //
  unsafe.putO

Copy into string rather than referencing buffer directly.