bool advanceCharacter(Decoder& it)
 {
     char32_t ch;
     if (!it.next(ch))
         return false;
     auto prevIt = it.getLogicalBegin();
     if (Decoder::isForward)
     {
         while (it.next(ch))
         {
             if (!Unicode::isMark(ch))
             {
                 it.setLogicalBegin(prevIt);
                 break;
             }
             prevIt = it.getLogicalBegin();
         }
     }
     else
     {
         while (Unicode::isMark(ch) && it.next(ch))
         {}
     }
     return true;
 }
 Decoder nextToken(Decoder& str, UnaryPredicate predicate)
 {
     auto token = str;
     token.setLogicalEnd(str.getLogicalBegin());
     char32_t ch;
     while (str.next(ch) && !predicate(ch))
         token.setLogicalEnd(str.getLogicalBegin());
     return token;
 }
 Decoder nextNewline(Decoder& str)
 {
     auto newline = str;
     char32_t ch;
     while (str.next(ch))
     {
         switch (ch)
         {
         case '\n':
             if (!Decoder::isForward)
             {
                 auto copyOfStr = str;
                 if (str.next(ch) && ch != '\r')
                     str.setLogicalBegin(copyOfStr.getLogicalBegin());
             }
             newline.setLogicalEnd(str.getLogicalBegin());
             return newline;
         case '\v':
         case '\f':
         case Unicode::NEXT_LINE:
         case Unicode::LINE_SEPARATOR:
         case Unicode::PARAGRAPH_SEPARATOR:
             newline.setLogicalEnd(str.getLogicalBegin());
             return newline;
         case '\r':
             if (Decoder::isForward)
             {
                 auto copyOfStr = str;
                 if (str.next(ch) && ch != '\n')
                     str.setLogicalBegin(copyOfStr.getLogicalBegin());
             }
             newline.setLogicalEnd(str.getLogicalBegin());
             return newline;
         default:
             break;
         }
         newline.setLogicalBegin(str.getLogicalBegin());
     }
     return str;
 }