nl_tokens: 从给定 offs 尽力匹配给出的数组。 <p > 需要注意的是，如果返回的是 > 0 的数，内部的标志位将被设置到第一个匹配字符，以便 DUMP 内容。 <br > 所以，如果下一个节点给出的结论是 - 1，但是 l 并不是0，那么说明这个匹配是失败的，需要将 本节点的 r 置到 max 处。 <p > 返回值 <ul > <li > <b > - 1< / b > - 全部被匹配 <li > <b > 0< / b > - 未发现匹配 <li > <b > 大于 0< / b > - 在缓冲的末尾发现匹配，但是没有匹配全，希望下一个节点继续从这个位置匹配 < / ul >
pl_tokens: int mark ( byte [ ] bs , int [ ] fails ) { if ( ! isLoaded ) throw new MarkUnloadedRingItemException ( ) ; byte start = bs [ 0 ] ; for ( ; r < <mask> ; r ++ ) { // 可能是边界，开始匹配
   if ( buffer [ r ] == start ) { int re = 0 ; // 已经匹配长度
   int j = r ; // 在内容值字节数组中的指针
   while ( true ) { re ++ ; j ++ ; // 全部匹配
   if ( re == bs . length ) { nextmark = j ; return - 1 ; } // 到达本项目的结尾，但是并不确定是否是边界，因为还未匹配完
   // 因此暂时假设这个不会被匹配
   if ( j == max ) { nextmark = max ; if ( isStreamEnd ) { r = max ; return 0 ; } return re ; } // 如果字符不相等，那么查看一下回退数组
   // 如果回退到 0，则退出循环，因为这不是边界，否则继续循环匹配边界
   if ( bs [ re ] != buffer [ j ] ) { re = fails [ re ] ; // 再次判断回退后位置，如果还是不相同，则退出循环
   if ( bs [ re ] != buffer [ j ] ) { break ; } // 如果已经回退到了 0，你这么右边界置为 j，表示从头搜索
   else if ( re == 0 ) { r = j ; } // 否则扩大边界，并继续循环
   else { r += re == 0 ? 1 : re ; } } } // make 'r' jump to 'j'
   r = j ; } } // Fail to found
   nextmark = max ; return 0 ; }