gt:                 if (curChar == 'u') {
context: /*
   * Copyright 2014 Higher Frequency Trading
   *
   * http://www.higherfrequencytrading.com
   *
   * Licensed 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 net.openhft.saxophone.json;
  
  import net.openhft.chronicle.bytes.Bytes;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  import static net.openhft.saxophone.json.LexError.*;
  import static net.openhft.saxophone.json.TokenType.*;
  
  /**
   * Porting note: this class approximately corresponds to src/yajl_lex.c and src/yajl_lex.h in YAJL.
   *
   * I tried to preserve method order and names to ease side-to-side comparison.
   */
  final class Lexer {
      private static final Logger LOG = LoggerFactory.getLogger(Lexer.class);
  
      /** Impact of the stream parsing feature on the lexer:
       *
       * YAJL support stream parsing.  That is, the ability to parse the first
       * bits of a chunk of JSON before the last bits are available (still on
       * the network or disk).  This makes the lexer more complex.  The
       * responsibility of the lexer is to handle transparently the case where
       * a chunk boundary falls in the middle of a token.  This is
       * accomplished is via a buffer and a character reading abstraction.
       *
       * Overview of implementation
       *
       * When we lex to end of input string before end of token is hit, we
       * copy all of the input text composing the token into our lexBuf.
       *
       * Every time we read a character, we do so through the readChar function.
       * readChar's responsibility is to handle pulling all chars from the buffer
       * before pulling chars from input text
       */
      /* a lookup table which lets us quickly determine three things:
       * VEC - valid escaped control char
       * note.  the solidus '/' may be escaped or not.
       * IJC - invalid json char
       * VHC - valid hex char
       * NFP - needs further processing (from a string scanning perspective)
       * NUC - needs utf8 checking when enabled (from a string scanning perspective)
       */
      private static final byte VEC = 0x01;
      private static final byte IJC = 0x02;
      private static final byte VHC = 0x04;
      private static final byte NFP = 0x08;
      private static final byte NUC = 0x10;
  
      private static final byte[] CHAR_LOOKUP_TABLE = {
       /*00*/ IJC, IJC, IJC        , IJC, IJC        , IJC, IJC    , IJC,
       /*08*/ IJC, IJC, IJC        , IJC, IJC        , IJC, IJC    , IJC,
       /*10*/ IJC, IJC, IJC        , IJC, IJC        , IJC, IJC    , IJC,
       /*18*/ IJC, IJC, IJC        , IJC, IJC        , IJC, IJC    , IJC,
  
       /*20*/ 0  , 0  , NFP|VEC|IJC, 0  , 0          , 0  , 0      , 0  ,
       /*28*/ 0  , 0  , 0          , 0  , 0          , 0  , 0      , VEC,
       /*30*/ VHC, VHC, VHC        , VHC, VHC        , VHC, VHC    , VHC,
       /*38*/ VHC, VHC, 0          , 0  , 0          , 0  , 0      , 0  ,
  
       /*40*/ 0  , VHC, VHC        , VHC, VHC        , VHC, VHC    , 0  ,
       /*48*/ 0  , 0  , 0          , 0  , 0          , 0  , 0      , 0  ,
       /*50*/ 0  , 0  , 0          , 0  , 0          , 0  , 0      , 0  ,
       /*58*/ 0  , 0  , 0          , 0  , NFP|VEC|IJC, 0  , 0      , 0  ,
  
       /*60*/ 0  , VHC, VEC|VHC    , VHC, VHC        , VHC, VEC|VHC, 0  ,
       /*68*/ 0  , 0  , 0          , 0  , 0          , 0  , VEC    , 0  ,
       /*70*/ 0  , 0  , VEC        , 0  , VEC        , 0  , 0      , 0  ,
       /*78*/ 0  , 0  , 0          , 0  , 0          , 0  , 0      , 0  ,
  
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
  
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
  
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
  
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC,
              NUC, NUC, NUC        , NUC, NUC        , NUC, NUC    , NUC
      };
  
      private static final char[] RUE_CHARS = new char[] {'r', 'u', 'e'};
      private static final char[] ALSE_CHARS = new char[] {'a', 'l', 's', 'e'};
      private static final char[] ULL_CHARS = new char[] {'u', 'l', 'l'};
      /** a input buffer to handle the case where a token is spread over multiple chunks */
      private final Bytes buf = Bytes.elasticByteBuffer();
      private final boolean allowComments;
      /** shall we validate utf8 inside strings? */
      private final boolean validateUTF8;
      LexError error;
      /** Emulating out parameters of lex() method. */
      Bytes outBuf;
      long outPos;
      long outLen;
      /**
       * are we using the lex buf?
       */
      private boolean bufInUse;
  
      Lexer(boolean allowComments, boolean validateUTF8) {
          this.allowComments = allowComments;
          this.validateUTF8 = validateUTF8;
      }
  
      void reset() {
          bufInUse = false;
          error = null;
          outBuf = null;
          outPos = outLen = 0;
      }
  
      private int readChar(Bytes txt) {
          if (bufInUse && buf.readRemaining() > 0) {
              return buf.readUnsignedByte();
  
          } else {
              return txt.readUnsignedByte();
          }
      }
  
      private void unreadChar(Bytes txt) {
          txt.readSkip(-1);
      }
  
      /** process a variable length utf8 encoded codepoint.
       *
       *  @return
       *    STRING - if valid utf8 char was parsed and offset was advanced
       *    EOF - if end of input was hit before validation could complete
       *    ERROR - if invalid utf8 was encountered
       *
       *  NOTE: on error the offset will point to the first char of the
       *  invalid utf8
       */
      private TokenType lexUtf8Char(Bytes jsonText, int curChar) {
          if (curChar <= 0x7f) {
              /* single byte */
              return STRING;
  
          } else if ((curChar >> 5) == 0x6) {
              /* two byte */
              if (jsonText.readRemaining() == 0) return EOF;
              curChar = readChar(jsonText);
              if ((curChar >> 6) == 0x2) return STRING;
  
          } else if ((curChar >> 4) == 0x0e) {
              /* three byte */
              if (jsonText.readRemaining() == 0) return EOF;
              curChar = readChar(jsonText);
              if ((curChar >> 6) == 0x2) {
                  if (jsonText.readRemaining() == 0) return EOF;
                  curChar = readChar(jsonText);
                  if ((curChar >> 6) == 0x2) return STRING;
              }
          } else if ((curChar >> 3) == 0x1e) {
              /* four byte */
              if (jsonText.readRemaining() == 0) return EOF;
              curChar = readChar(jsonText);
              if ((curChar >> 6) == 0x2) {
                  if (jsonText.readRemaining() == 0) return EOF;
                  curChar = readChar(jsonText);
                  if ((curChar >> 6) == 0x2) {
                      if (jsonText.readRemaining() == 0) return EOF;
                      curChar = readChar(jsonText);
                      if ((curChar >> 6) == 0x2) return STRING;
                  }
              }
          }
          return ERROR;
      }
  
      /**
       * scan a string for interesting characters that might need further
       * review.  return the number of chars that are uninteresting and can
       * be skipped.
       * (lth) hi world, any thoughts on how to make this routine faster?
       */
      private void stringScan(Bytes bytes) {
          int mask = IJC | NFP | (validateUTF8 ? NUC : 0);
          long pos = bytes.readPosition();
          long limit = bytes.readLimit();
          while (pos < limit && ((CHAR_LOOKUP_TABLE[bytes.readUnsignedByte(pos)] & mask) == 0)) {
              pos++;
          }
          bytes.readPosition(pos);
      }
  
      /**
       * Lex a string.
       *
       *  @return
       *     STRING - lex of string was successful.  offset points to terminating '"'.
       *     EOF - end of text was encountered before we could complete the lex.
       *     ERROR - embedded in the string were unallowable chars.  offset
       *             points to the offending char
       */
      private TokenType lexString(Bytes jsonText) {
          TokenType tok = ERROR;
          boolean hasEscapes = false;
  
          finish_string_lex:
          for (;;) {
              int curChar;
  
              /* now jump into a faster scanning routine to skip as much
               * of the buffers as possible */
              {
                  if (bufInUse && buf.readRemaining() > 0) {
                      stringScan(buf);
  
                  } else if (jsonText.readRemaining() > 0) {
                      stringScan(jsonText);
                  }
              }
  
              if (jsonText.readRemaining() == 0) {
                  tok = EOF;
                  break;
              }
  
              curChar = readChar(jsonText);
  
              /* quote terminates */
              if (curChar == '"') {
                  tok = STRING;
                  break;
              }
              /* backslash escapes a set of control chars, */
              else if (curChar == '\\') {
                  hasEscapes = true;
                  if (jsonText.readRemaining() == 0) {
                      tok = EOF;
                      break;
                  }
  
                  /* special case \\u */
                  curChar = readChar(jsonText);
  