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; }