private void end(State start, State end, UTF8Sequence utf8, int upto, boolean doAll) {
   if (upto == utf8.len - 1) {
     // Done recursing
     start.addTransition(
         new Transition(
             utf8.byteAt(upto) & (~MASKS[utf8.numBits(upto) - 1]),
             utf8.byteAt(upto),
             end)); // type=end
   } else {
     final int startCode;
     if (utf8.numBits(upto) == 5) {
       // special case -- avoid created unused edges (utf8
       // doesn't accept certain byte sequences) -- there
       // are other cases we could optimize too:
       startCode = 194;
     } else {
       startCode = utf8.byteAt(upto) & (~MASKS[utf8.numBits(upto) - 1]);
     }
     if (doAll && utf8.byteAt(upto) != startCode) {
       all(start, end, startCode, utf8.byteAt(upto) - 1, utf8.len - upto - 1);
     }
     State n = newUTF8State();
     start.addTransition(new Transition(utf8.byteAt(upto), n)); // type=end
     end(n, end, utf8, 1 + upto, true);
   }
 }
 private void start(State start, State end, UTF8Sequence utf8, int upto, boolean doAll) {
   if (upto == utf8.len - 1) {
     // Done recursing
     start.addTransition(
         new Transition(
             utf8.byteAt(upto),
             utf8.byteAt(upto) | MASKS[utf8.numBits(upto) - 1],
             end)); // type=start
   } else {
     State n = newUTF8State();
     start.addTransition(new Transition(utf8.byteAt(upto), n)); // type=start
     start(n, end, utf8, 1 + upto, true);
     int endCode = utf8.byteAt(upto) | MASKS[utf8.numBits(upto) - 1];
     if (doAll && utf8.byteAt(upto) != endCode) {
       all(start, end, utf8.byteAt(upto) + 1, endCode, utf8.len - upto - 1);
     }
   }
 }