RegexModifier implements Modifier { @Override public AfterModification modify(StringBuilder characterBuffer, int firstModifiableCharacterInBuffer, boolean endOfStreamHit) { Integer minFrom = null; while (true) { if (minFrom == null) { minFrom = firstModifiableCharacterInBuffer; if (unseenCharactersToSkip > 0) { if (minFrom + unseenCharactersToSkip > characterBuffer.length()) { if (endOfStreamHit) { return factory.stop(characterBuffer, firstModifiableCharacterInBuffer, endOfStreamHit); } else { return factory.fetchMoreInput(0, characterBuffer, firstModifiableCharacterInBuffer, endOfStreamHit); } } else { minFrom += unseenCharactersToSkip; unseenCharactersToSkip = 0; } } } int maxFrom = firstModifiableCharacterInBuffer + newNumberOfChars; if (maxFrom > characterBuffer.length()) { maxFrom = characterBuffer.length(); } matcher.reset(characterBuffer); boolean matchFound = matcher.findUnlessHitEnd(minFrom, maxFrom); if (matchFound) { if (matcher.hitEnd() && !endOfStreamHit) { int numberOfCharactersToSkip = matcher.lastFrom() - firstModifiableCharacterInBuffer; AfterModification mod = factory.fetchMoreInput(numberOfCharactersToSkip, characterBuffer, firstModifiableCharacterInBuffer, endOfStreamHit); assert __checkpoint( "name", "match_open", "minLen", firstModifiableCharacterInBuffer, "characterBuffer", characterBuffer, "endOfStreamHit", endOfStreamHit, "afterModification", mod); return mod; } else { MatchResult matchResult = matcher; MatchProcessorResult matchProcessorResult = matchProcessor.process(characterBuffer, minFrom, matchResult); minFrom = matchProcessorResult.getFirstModifiableCharacterInBuffer(); if (minFrom <= maxFrom && matchProcessorResult.isContinueMatching()) { assert __checkpoint( "name", "match_n_continue", "minLen", firstModifiableCharacterInBuffer, "characterBuffer", characterBuffer, "endOfStreamHit", endOfStreamHit, "minFrom", minFrom); continue; } else { int numberOfCharactersToSkip; if (minFrom > characterBuffer.length()) { unseenCharactersToSkip = minFrom - characterBuffer.length(); ZzzAssert.isTrue(unseenCharactersToSkip == 1, "unseenCharactersToSkip must be one but was " + unseenCharactersToSkip); numberOfCharactersToSkip = characterBuffer.length() - firstModifiableCharacterInBuffer; } else { numberOfCharactersToSkip = minFrom - firstModifiableCharacterInBuffer; } if (numberOfCharactersToSkip == 0) { AfterModification mod = factory.fetchMoreInput(numberOfCharactersToSkip, characterBuffer, firstModifiableCharacterInBuffer, false); assert __checkpoint( "name", "match_n_refill", "minLen", firstModifiableCharacterInBuffer, "characterBuffer", characterBuffer, "endOfStreamHit", endOfStreamHit, "afterModification", mod); return mod; } else { AfterModification mod = factory.skipOrStop(numberOfCharactersToSkip, characterBuffer, firstModifiableCharacterInBuffer, endOfStreamHit); assert __checkpoint( "name", "match_n_skip", "minLen", firstModifiableCharacterInBuffer, "characterBuffer", characterBuffer, "endOfStreamHit", endOfStreamHit, "afterModification", mod); return mod; } } } } else { if (matcher.lastFrom() <= maxFrom) { if (endOfStreamHit) { int numberOfCharactersToSkip = maxFrom - firstModifiableCharacterInBuffer; AfterModification mod = factory.skipOrStop(numberOfCharactersToSkip, characterBuffer, firstModifiableCharacterInBuffer, endOfStreamHit); assert __checkpoint( "name", "nomatch_eos", "minLen", firstModifiableCharacterInBuffer, "characterBuffer", characterBuffer, "endOfStreamHit", endOfStreamHit, "afterModification", mod); return mod; } else { int numberOfCharactersToSkip = matcher.lastFrom() - firstModifiableCharacterInBuffer; AfterModification mod = factory.fetchMoreInput(numberOfCharactersToSkip, characterBuffer, firstModifiableCharacterInBuffer, endOfStreamHit); assert __checkpoint( "name", "nomatch_fetch", "minLen", firstModifiableCharacterInBuffer, "characterBuffer", characterBuffer, "endOfStreamHit", endOfStreamHit, "afterModification", mod); return mod; } } else { int numberOfCharactersToSkip = maxFrom - firstModifiableCharacterInBuffer; AfterModification mod = factory.skipOrStop(numberOfCharactersToSkip, characterBuffer, firstModifiableCharacterInBuffer, endOfStreamHit); assert __checkpoint( "name", "nomatch_skip", "minLen", firstModifiableCharacterInBuffer, "characterBuffer", characterBuffer, "endOfStreamHit", endOfStreamHit, "afterModification", mod); return mod; } } } } protected  RegexModifier();  RegexModifier(String regex, int flags, String replacement);  RegexModifier(String regex, int flags, String replacement, int minimumLengthOfLookBehind,
            int newNumberOfChars);  RegexModifier(String regex, int flags, MatchProcessor matchProcessor, int minimumLengthOfLookBehind,
            int newNumberOfChars);  RegexModifier(OnStreamMatcher matcher, MatchProcessor matchProcessor, int minimumLengthOfLookBehind,
            int newNumberOfChars); @Override AfterModification modify(StringBuilder characterBuffer, int firstModifiableCharacterInBuffer,
            boolean endOfStreamHit); @Override String toString(); void setMatchProcessor(MatchProcessor matchProcessor);  }
@Test public void testExampleFromHomepage_advancedExample_firstImprovement() throws Exception { Modifier myModifier = new RegexModifier("edit stream", 0, "modify stream"); assertNotEquals("modify\tstream", modify("edit\tstream", myModifier)); assertNotEquals("modify\nstream", modify("edit\nstream", myModifier)); Modifier myModifier1 = new RegexModifier("edit\\sstream", Pattern.DOTALL, "modify stream"); assertEquals("modify stream", modify("edit\tstream", myModifier1)); assertEquals("modify stream", modify("edit\nstream", myModifier1)); }
@Test public void testExampleFromHomepage_advancedExample_secondImprovement() throws Exception { Modifier myModifier1 = new RegexModifier("edit\\sstream", Pattern.DOTALL, "modify stream"); assertNotEquals("modify\tstream", modify("edit\tstream", myModifier1)); assertNotEquals("modify stream", modify("edit stream", myModifier1)); Modifier myModifier2 = new RegexModifier("edit(\\s++stream)", Pattern.DOTALL, "modify$1"); assertEquals("modify\tstream", modify("edit\tstream", myModifier2)); assertEquals("modify stream", modify("edit stream", myModifier2)); }
@Test public void testExampleFromHomepage_advancedExample_thirdImprovement() throws Exception { Modifier myModifier2 = new RegexModifier("edit(\\s++stream)", Pattern.DOTALL, "modify$1"); assertNotEquals("credit stream", modify("credit stream", myModifier2)); Modifier myModifier3 = new RegexModifier("(?<=\\s)edit(\\s++stream)", Pattern.DOTALL, "modify$1", 1, 2048); assertEquals("credit stream", modify("credit stream", myModifier3)); }
@Test public void testExampleFromHomepage_advancedExample_greedyQuantifierOnDot() throws Exception { Modifier myModifier4 = new RegexModifier("edit.*stream", 0, "modify stream"); assertNotEquals("modify stream modify stream", modify("edit stream edit stream", myModifier4)); Modifier myModifier5 = new RegexModifier("edit\\s*stream", 0, "modify stream"); assertNotEquals("modify stream modify stream", modify("edit stream edit stream", myModifier5)); }