content: // Copyright 2010 The Go Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style
  // license that can be found in the LICENSE file.
  
  // Original Go source here:
  // http://code.google.com/p/go/source/browse/src/pkg/regexp/regexp.go
  
  package com.github.aaronshan.functions.regexp.re2j;
  
  import io.airlift.slice.Slice;
  import sun.misc.Unsafe;
  
  import java.lang.reflect.Field;
  
  /**
   * MachineInput represents the UTF-8 input text supplied to the Machine. It provides one-character
   * lookahead.
   */
  final class MachineInput {
  
      static final byte EOF = -1;
      private static final Unsafe unsafe;
  
      static {
          try {
              // fetch theUnsafe object
              Field field = Unsafe.class.getDeclaredField("theUnsafe");
              field.setAccessible(true);
              unsafe = (Unsafe) field.get(null);
              if (unsafe == null) {
                  throw new RuntimeException("Unsafe access not available");
              }
          } catch (Exception e) {
              throw new RuntimeException(e);
          }
      }
  
      final Slice slice;
      final Object base;
      final long address;
      final int length;
      MachineInput(Slice slice) {
          this.slice = slice;
          this.base = slice.getBase();
          this.address = slice.getAddress();
          this.length = slice.length();
      }
  
      static MachineInput fromUTF8(Slice slice) {
          return new MachineInput(slice);
      }
  
      // Returns the byte at the specified index.
      byte getByte(int i) {
          if (i >= length) {
              return EOF;
          }
  
          if (i < 0) {
              throw new IndexOutOfBoundsException("index less than zero (" + i + ")");
          }
  
          return getByteUnchecked(i);
      }
  
      byte getByteUnchecked(int i) {
          return unsafe.getByte(base, address + i);
      }
  
      // Returns the index relative to |pos| at which |re2.prefix| is found
      // in this input stream, or a negative value if not found.
      int index(RE2 re2, int pos) {
          int i = Utils.indexOf(slice, re2.prefixUTF8, pos);
          return i < 0 ? i : i - pos;
      }
  
      // Returns the end position in the same units as step().
      int endPos() {
          return length;
      }
  }
  