larksuite-oapi/src/main/java/com/larksuite/oapi/okio1_17/Buffer.java
int selectPrefix(Options options, boolean selectTruncated) {
    Segment head = this.head;
    if (head == null) {
      if (selectTruncated) return -2; // A result is present but truncated.
      return options.indexOf(ByteString.EMPTY);
    }

    Segment s = head;
    byte[] data = head.data;
    int pos = head.pos;
    int limit = head.limit;

    int[] trie = options.trie;
    int triePos = 0;

    int prefixIndex = -1;

    navigateTrie:
    while (true) {
      int scanOrSelect = trie[triePos++];

      int possiblePrefixIndex = trie[triePos++];
      if (possiblePrefixIndex != -1) {
        prefixIndex = possiblePrefixIndex;
      }

      int nextStep;

      if (s == null) {
        break;
      } else if (scanOrSelect < 0) {
        // Scan: take multiple bytes from the buffer and the trie, looking for any mismatch.
        int scanByteCount = -1 * scanOrSelect;
        int trieLimit = triePos + scanByteCount;
        while (true) {
          int b = data[pos++] & 0xff;
          if (b != trie[triePos++]) return prefixIndex; // Fail 'cause we found a mismatch.
          boolean scanComplete = (triePos == trieLimit);

          // Advance to the next buffer segment if this one is exhausted.
          if (pos == limit) {
            s = s.next;
            pos = s.pos;
            data = s.data;
            limit = s.limit;
            if (s == head) {
              if (!scanComplete) break navigateTrie; // We were exhausted before the scan completed.
              s = null; // We were exhausted at the end of the scan.
            }
          }

          if (scanComplete) {
            nextStep = trie[triePos];
            break;
          }
        }
      } else {
        // Select: take one byte from the buffer and find a match in the trie.
        int selectChoiceCount = scanOrSelect;
        int b = data[pos++] & 0xff;
        int selectLimit = triePos + selectChoiceCount;
        while (true) {
          if (triePos == selectLimit) return prefixIndex; // Fail 'cause we didn't find a match.

          if (b == trie[triePos]) {
            nextStep = trie[triePos + selectChoiceCount];
            break;
          }

          triePos++;
        }

        // Advance to the next buffer segment if this one is exhausted.
        if (pos == limit) {
          s = s.next;
          pos = s.pos;
          data = s.data;
          limit = s.limit;
          if (s == head) {
            s = null; // No more segments! The next trie node will be our last.
          }
        }
      }

      if (nextStep >= 0) return nextStep; // Found a matching option.
      triePos = -nextStep; // Found another node to continue the search.
    }

    // We break out of the loop above when we've exhausted the buffer without exhausting the trie.
    if (selectTruncated) return -2; // The buffer is a prefix of at least one option.
    return prefixIndex; // Return any matches we encountered while searching for a deeper match.
  }
/**
   * Returns the index of a value in options that is a prefix of this buffer. Returns -1 if no value
   * is found. This method does two simultaneous iterations: it iterates the trie and it iterates
   * this buffer. It returns when it reaches a result in the trie, when it mismatches in the trie,
   * and when the buffer is exhausted.
   *
   * @param selectTruncated true to return -2 if a possible result is present but truncated. For
   *     example, this will return -2 if the buffer contains [ab] and the options are [abc, abd].
   *     Note that this is made complicated by the fact that options are listed in preference order,
   *     and one option may be a prefix of another. For example, this returns -2 if the buffer
   *     contains [ab] and the options are [abc, a].
   */
Returns the index of a value in options that is a prefix of this buffer. Returns -1 if no value
is found. This method does two simultaneous iterations: it iterates the trie and it iterates
this buffer. It returns when it reaches a result in the trie, when it mismatches in the trie,
and when the buffer is exhausted.

@param selectTruncated true to return -2 if a possible result is present but truncated. For
example, this will return -2 if the buffer contains [ab] and the options are [abc, abd].
Note that this is made complicated by the fact that options are listed in preference order,
and one option may be a prefix of another. For example, this returns -2 if the buffer
contains [ab] and the options are [abc, a].
Returns the index of a value in options that is a prefix of this buffer . Returns - 1 if no value is found . This method does two simultaneous iterations : it iterates the trie and it iterates this buffer . It returns when it reaches a result in the trie when it mismatches in the trie and when the buffer is exhausted . @param selectTruncated true to return - 2 if a possible result is present but truncated . For example this will return - 2 if the buffer contains [ ab ] and the options are [ abc abd ] . Note that this is made complicated by the fact that options are listed in preference order and one option may be a prefix of another . For example this returns - 2 if the buffer contains [ ab ] and the options are [ abc a ] .
int selectPrefix(Options options, boolean selectTruncated) {
    Segment head = this.head;
    if (head == null) {
      if (selectTruncated) return -2; 
      return options.indexOf(ByteString.EMPTY);
    }
    Segment s = head;
    byte[] data = head.data;
    int pos = head.pos;
    int limit = head.limit;
    int[] trie = options.trie;
    int triePos = 0;
    int prefixIndex = -1;
    navigateTrie:
    while (true) {
      int scanOrSelect = trie[triePos++];
      int possiblePrefixIndex = trie[triePos++];
      if (possiblePrefixIndex != -1) {
        prefixIndex = possiblePrefixIndex;
      }
      int nextStep;
      if (s == null) {
        break;
      } else if (scanOrSelect < 0) {
        int scanByteCount = -1 * scanOrSelect;
        int trieLimit = triePos + scanByteCount;
        while (true) {
          int b = data[pos++] & 0xff;
          if (b != trie[triePos++]) return prefixIndex; 
          boolean scanComplete = (triePos == trieLimit);
          if (pos == limit) {
            s = s.next;
            pos = s.pos;
            data = s.data;
            limit = s.limit;
            if (s == head) {
              if (!scanComplete) break navigateTrie; 
              s = null; 
            }
          }
          if (scanComplete) {
            nextStep = trie[triePos];
            break;
          }
        }
      } else {
        int selectChoiceCount = scanOrSelect;
        int b = data[pos++] & 0xff;
        int selectLimit = triePos + selectChoiceCount;
        while (true) {
          if (triePos == selectLimit) return prefixIndex; 
          if (b == trie[triePos]) {
            nextStep = trie[triePos + selectChoiceCount];
            break;
          }
          triePos++;
        }
        if (pos == limit) {
          s = s.next;
          pos = s.pos;
          data = s.data;
          limit = s.limit;
          if (s == head) {
            s = null; 
          }
        }
      }
      if (nextStep >= 0) return nextStep; 
      triePos = -nextStep; 
    }
    if (selectTruncated) return -2; 
    return prefixIndex; 
  }
int selectPrefix ( Options options , boolean selectTruncated ) { Segment head = this . head ; if ( head == null ) { if ( selectTruncated ) return - 2 ; return options . indexOf ( ByteString . EMPTY ) ; } Segment s = head ; byte [ ] data = head . data ; int pos = head . pos ; int limit = head . limit ; int [ ] trie = options . trie ; int triePos = 0 ; int prefixIndex = - 1 ; navigateTrie : while ( true ) { int scanOrSelect = trie [ triePos ++ ] ; int possiblePrefixIndex = trie [ triePos ++ ] ; if ( possiblePrefixIndex != - 1 ) { prefixIndex = possiblePrefixIndex ; } int nextStep ; if ( s == null ) { break ; } else if ( scanOrSelect < 0 ) { int scanByteCount = - 1 * scanOrSelect ; int trieLimit = triePos + scanByteCount ; while ( true ) { int b = data [ pos ++ ] & 0xff ; if ( b != trie [ triePos ++ ] ) return prefixIndex ; boolean scanComplete = ( triePos == trieLimit ) ; if ( pos == limit ) { s = s . next ; pos = s . pos ; data = s . data ; limit = s . limit ; if ( s == head ) { if ( ! scanComplete ) break navigateTrie ; s = null ; } } if ( scanComplete ) { nextStep = trie [ triePos ] ; break ; } } } else { int selectChoiceCount = scanOrSelect ; int b = data [ pos ++ ] & 0xff ; int selectLimit = triePos + selectChoiceCount ; while ( true ) { if ( triePos == selectLimit ) return prefixIndex ; if ( b == trie [ triePos ] ) { nextStep = trie [ triePos + selectChoiceCount ] ; break ; } triePos ++ ; } if ( pos == limit ) { s = s . next ; pos = s . pos ; data = s . data ; limit = s . limit ; if ( s == head ) { s = null ; } } } if ( nextStep >= 0 ) return nextStep ; triePos = - nextStep ; } if ( selectTruncated ) return - 2 ; return prefixIndex ; }
Returns the index of a value in options that is a prefix of this buffer.
Returns the index of a value in options that is a prefix of this buffer .
// A result is present but truncated. // Scan: take multiple bytes from the buffer and the trie, looking for any mismatch. // Fail 'cause we found a mismatch. // Advance to the next buffer segment if this one is exhausted. // We were exhausted before the scan completed. // We were exhausted at the end of the scan. // Select: take one byte from the buffer and find a match in the trie. // Fail 'cause we didn't find a match. // Advance to the next buffer segment if this one is exhausted. // No more segments! The next trie node will be our last. // Found a matching option. // Found another node to continue the search. // We break out of the loop above when we've exhausted the buffer without exhausting the trie. // The buffer is a prefix of at least one option. // Return any matches we encountered while searching for a deeper match.